Closed5
Flutter エンジニア向け Android の Activity とライフサイクルの基礎知識

(社内勉強会向けの資料です)
モチベーション
- Android ネイティブ未経験の Flutter エンジニアに向けて、Android の Activity とライフサイクルについて簡単に解説
- Flutter で作った Android アプリがどのように動いているのか、より納得感を持って開発する
- Add-to-app を使っている場合、つなぎ込みの担当者は、どのような開発を行っているのか理解する
- camera パッケージなど、ライフサイクルに密接に関わるパッケージを使った開発において、挙動をイメージしやすくする

Activity
- Android のいわゆる画面
- スタックのように積むことができて、バックキーや finish() メソッド呼び出しで、今見えている画面を取り除くことで、前の画面に戻れる
- ランチャーアイコンから起動できる Android アプリには、必ず1つ以上ある
Flutter アプリにおける Activity
- Flutter を描画する FlutterActivity が、かならず1つ以上ある。
- Flutter プロジェクトだと android ディレクトリの奥深くにある MainActivity が該当する。

ライフサイクル
Activity にはライフサイクルがある
ライフサイクル名 | 内容 |
---|---|
onCreate | Activity が作られた。アプリ起動時や、別の画面から呼ばれたときが該当する。 |
onResume | Activity がフォアグランドになった。上に被さっている Activity が終了したときや、別のアプリから切り替えた時が該当する。 |
onPause | Activity がバックグランドになった。ホームボタンを押したり、別の Activity が上に被さった時が該当する。 |
onDestory | Activity が破棄された。バックキーで前の画面に戻った場合が該当する。 |
厳密には onStart と onStop があるが省略。
Flutter アプリにおける Android のライフサイクル
通常は気にしなくて良いが、カメラや GPS など、デバイスの機能を使う場合は、意識する必要がある。
camera パッケージにはこのような解説がある。
class _CameraScreenObserver extends WidgetsBindingObserver {
void didChangeAppLifecycleState(AppLifecycleState state) {
final CameraController? cameraController = controller;
// App state changed before we got the chance to initialize.
if (cameraController == null || !cameraController.value.isInitialized) {
return;
}
if (state == AppLifecycleState.inactive) { // Android の onPause に該当
cameraController.dispose();
} else if (state == AppLifecycleState.resumed) { // Android の onResume に該当
_initializeCameraController(cameraController.description);
}
}
}
上記インスタンスをこのように使う。
WidgetsBinding.instance.addObserver(this);
WidgetsBinding.instance.removeObserver(this);
Flutter でライフサイクルを無視した場合
カメラの場合、ホームボタンを押してアプリをバックグランドにして、別のアプリを開いたとする。その別アプリがカメラを使いたくても、カメラを掴んだままなので、使えなくなる。
バックグランドになったタイミングで解放する必要がある。

画面遷移
Android においては3種類ある。
- Activity 呼び出しによる画面遷移
- Fragment による画面遷移
- Compose による画面遷移
Activity
- Intent を作って startActivity 関数で上に被せることができる。
val intent = Intent(this, MemberActivity::class.java)
intent.putInt("userId", 123) // 引数も渡せる
startActivity(intent)
- Activity が結果を持つことができる。
- 閉じたときに結果を受け取る方法もある。
val data = Intent()
data.putBoolean("favorite", true)
setResult(RESULT_OK, data)
- いいね問題の古典的な解決に使える
Fragment
- Activity 内の矩形で Activity と同様のライフサイクルがある
- Fragment は単独では存在できない。かならず Activity に載っている。
- Activity の中で Fragment を切り替えたり、積むことができる
- 誕生の経緯は 2011年リリースのタブレット用 OS - Android 3.0。リストと詳細 Fragment にして、スマホでは別に使い、タブレットでは横に並べて使うことを想定。
- ボトムナビゲーションのボタンを押して表示を切り替えている部分は、表示 Fragment を切り替えている。
Compose
- 2021年に安定版がリリースされた、宣言的 UI フレームワークによる画面遷移
- それより前の Android 1.0 からあった UI フレームワークは View や XML レイアウトと呼ばれる
- 必ず Activity に載っている
- Activity に載っている Fragment に載っていることもある。
Flutter の Add-to-app においては
- FlutterActivity から別の Activity を呼び出す
- View や Compose で作った Activity から FlutterActivity を呼び出す
- FlutterFragment もある

Jetpack
- Activity, Fragment は OS に標準搭載されている Android SDK に実装されているが、直接それらを使うことは無い。
- Jetpack という Google 標準のライブラリ群を使う
- OS アップデートにより SDK の使い方が変わることがあるが、Jetpack が吸収する
- 便利な機能が追加されている
- 分かりやすいものだと Edge-to-edge。中のソースコードを見ると OS バージョン別分岐がすごい。
このスクラップは2ヶ月前にクローズされました
作成者以外のコメントは許可されていません