目次
概要
- Android Developer Accountを放置していたらPlay Console 要件に合うように更新する通知が来た
- 趣味として、久しぶりにAndorid開発を行い、アカウントを維持する事に決めた
- 最近のAndroid開発ではJetpack ComposeとKotlinで開発するのが主流らしいので色々メモを残す
Androidの全般
スレッド
メインスレッドとは
メインスレッドは、UIスレッドとも呼ばれる
アプリケーションの起動時に作成される最初のスレッド
ユーザーインターフェース(UI)の描画と更新を担当する
主な役割
- UIコンポーネントの描画と更新
- ユーザー入力(タッチ、クリックなど)のイベント処理
- Activityのライフサイクルメソッドの実行
重要性
- アプリケーションの応答性を維持するために重要
- メインスレッドがブロックされると、アプリがフリーズしたように見える(ANR: Application Not Responding)
バックグラウンドスレッド
- アプリケーションのメインスレッド(UIスレッド)とは別に実行されるスレッドのこと
- Service Componentは、デフォルトでバックグラウンドスレッドではなくメインスレッドで動くので注意
Thread
やHandlerThread
、AsyncTask(現在は非推奨)
、Executors
、あるいはCoroutine
などを利用する必要がある
バックグラウンドスレッドは、以下のような処理に利用される。
- ネットワーク通信
- データベース操作
- ファイルI/O
- 長時間かかる計算処理
ベストプラクティス
- Applicationでシングルトンに管理するべき
- ViewModel, 常に動くforeground serviceなど
- 画面に関係ないのに、Activity頻繁にbindなどをして、別コンポーネントの作成と破棄を繰り返すと状態が複雑化する
- 普通にUI以外のコンポーネントはApplicationでシングルトンにしした方がいい
- つまり、できるだけ破棄再作成されないようなシンプルなStateにした方がいいですよね?
- 長時間実行される処理をメインスレッドで行うべきではない
- ネットワーク操作やデータベース処理などの時間のかかる操作は避ける
- ちなみに、WebのJSのFetchは非同期処理
- 時間のかかる操作は別のスレッドで実行する(AsyncTask, Coroutines, WorkManagerなど)
- ネットワーク操作やデータベース処理などの時間のかかる操作は避ける
- UIの更新はメインスレッドで行う
- なぜなら、Android のUI コンポーネントはスレッドセーフではないから
- 複数のスレッドから同時にUIを操作すると、競合状態や予期せぬ動作が発生する可能性があるから
- そのため、
runOnUiThread()
やHandler.post()
メソッドを使用して、バックグラウンドスレッドからメインスレッドに処理を戻す - Android システムは、MainThread 以外からのUI操作を検出し、例外をスローする(
CalledFromWrongThreadException
)。
メインスレッドでの処理とバックグラウンド処理の例。
|
|
もしくは下のような感じ。
|
|
ANR(Application Not Responding)
- ANRは、Application Not Respondingの略
![ANRのダイアログ(image-8.png)
ANRの発生条件は以下の2つ。
- 入力イベント(キーの押下や画面タッチなどのイベント)に対する応答が 5 秒以内にない
- BroadcastReceiverの実行が 10 秒以内に終了しない
スレッド vs. コルーチン
スレッドとコルーチンの図
- Process > Thread > Coroutineの階層
- KotlinはStructured Coroutineを採用しているのでCoroutineはさらに階層構造を持つ
- AndroidはMain Thread(UI Thread)とそれ以外のBackground Threadがある
- ちなみに、AndroidのServiceは、MainThreadで実行される
コルーチンのメリット
- Kotlinの場合は階層構造のcoroutine構造を持つ事によるグループ処理が可能
- また、Threadと違い、一時停止と再開、取り消しなどが可能となる
スレッドの例
Android でスレッドを使用する例。
- スレッド関数を使用して新しいスレッドを作成し、指定されたタスクを非同期で実行する
- ただし、競合状態、デッドロック、スレッド同期などの問題により、スレッドを直接操作することが困難な場合がある
|
|
コルーチンの例
- コルーチンは、並行処理をより構造化して効率的に処理する方法を提供する
|
|
画像をDLして表示する例
スレッドの例
|
|
Coroutinesの例
- withContextを使用してIO Dispatchersに切り替えてイメージをダウンロードしている
- その後Mainディスパッチャーに戻って UI を更新
|
|
versionCodeとversionName
- versionCode
- 整数で設定。
- ユーザーには表示されない。
- リリースのたびにIncrementする必要がある
- versionName
- 文字列で設定。
- 例えば、
1.1
とか2.1.4
のような値が設定できる - ユーザーに表示される
APK vs. AAB
- AABファイルは、Google Playが最適化されたAPKを生成するためのパッケージフォーマット
- ユーザーがアプリをインストールする際に、Google Playはデバイスに最適なAPKを生成して配布する
- そのため、例えば、Google DriveからインストールしたかったらAPKを選ぶ
Androidアプリの設計思想
- コンポーネントベース
- Androidアプリは主に4つの基本コンポーネント(Activity、Service、BroadcastReceiver、ContentProvider)から構成されている
- イベント駆動
- ユーザー操作やシステムイベントに応じて動作する
- インテント通信
- コンポーネント間やアプリ間の通信にはIntentシステムを使用する
- ライフサイクル管理
- 各コンポーネントには明確なライフサイクルがある
- それらはシステムによって管理される
- UIスレッドとバックグラウンド処理
- メインスレッド(UIスレッド)とバックグラウンドスレッドの分離を推奨している
アイコンの生成
アイコンの作成方法は次の手順。
Menu > File > new > Vector Asset
アイコンは次の2種類のclipartを用意する。
- ic_launcher
- size: 24dp x 24dp
- アプリ全般用
- ic_notification
- size: 48dp x 48dp
- 通知バー用のアイコン
Store用のアイコンは次を使う。
- Storeでのアプリのアイコン
AndroidStudioProjects\XXX\app\src\main\ic_launcher-playstore.png
- フィーチャーグラフィック
- スクリーンショット
- EmulatorでSSを撮る
Lifecycle
Lifecycleとは
- Androidの各コンポーネント(Activity、Fragment、Service等)は異なるライフサイクルを持つ
- ただし、課題が多いため、AndroidはLifecycleOwnerやViewModel、LiveDataなどのJetpack Componentsを推奨している
Lifecycleの違いによる問題は以下
- 複雑性の増加
- 各コンポーネントのライフサイクルが異なるため、開発者は各々の挙動を理解し、適切に処理する必要がある
- 複数のコンポーネントを組み合わせて使用する際、それぞれのライフサイクルの相互作用を考慮する必要がある
- メモリーリーク
- ライフサイクルの理解が不十分だと、不適切なタイミングでリソースの解放を忘れ、メモリリークを引き起こす可能性がある
- 例:Activityが破棄されても、長時間実行されるバックグラウンドタスクがActivityへの参照を保持し続ける場合など
- リソース管理
- カメラやGPS等のシステムリソースの使用開始/終了タイミングを、各コンポーネントのライフサイクルに合わせて適切に管理する必要がある
Componentのライフスパン
- Application
- プロセスと同等
- Activity, Service, Foreground Service
- メインスレッド
- AsyncTask, Kotlin Coroutines, HandlerThread
- バックグラウンドスレッド
Lifecycleのデバッグ
tagを決めて全メソッドに下を入れてtagでグルーピングしてデバッグするのが一番良い。
|
|
- ChatGPTでログをシーケンス図にするのが良い
- 以下はそのプロンプト
|
|
Andorid Component
代表的なコンポーネント一覧
Androidの代表的なコンポーネントは以下の通り。
- Activity
- ユーザーインターフェースを提供する単一の画面
- ユーザーと直接対話する部分を担当
- Service
- バックグラウンドで動作するコンポーネント
- ユーザーインターフェースを持たず、長時間実行されるタスクや他のコンポーネントと通信を行うタスクに使用される
- Broadcast Receiver
- システムや他のアプリからのブロードキャストメッセージを受信する
- ブロードキャストは、システムイベントやアプリからのカスタムイベントを通知するために使用される
- システムイベントは、例えば、バッテリーが低下やWi-Fiの接続など
- Content Provider
- アプリ間でデータを共有するための仕組みを提供する
- 例えば、連絡先アプリやメディアファイルへのアクセスなどがこれに該当する
- Fragment
- アクティビティの一部として動作するUIコンポーネント
- アクティビティ内での再利用可能なUI部分を作成するために使用される
- ViewModel
- アクティビティやフラグメントにおけるUIデータの管理を担当する
- ライフサイクルを考慮して設計されている
- 画面回転や他のライフサイクルイベントによってUIコントローラが再作成されても、データを保持する
- これにより、データの保存と復元のためのコードが簡素化される
- Application
- アプリケーションの全体的な状態を管理するためのベースクラス
- アプリケーション全体の初期化処理やグローバルな状態を保持するために使用される
- Applicationクラスを拡張し、必要に応じてカスタム初期化コードを追加できる
- LiveData
- ライフサイクルに依存したデータホルダーで、データが変更されると自動的に観察者に通知する
- ViewModelと一緒に使用されることが多く、UIのデータ更新を簡素化する
- Navigation
- アプリ内の画面遷移を管理するためのコンポーネント
- ナビゲーショングラフを使用して、アプリのフローを定義し、アクションや遷移を視覚的に設計することができる
- Repository
- データ操作を行うクラスで、データソースとViewModelの間の抽象層として機能する
- クリーンアーキテクチャの一部として使用されることが多い
Activity
Activityとは
- Activityは、AndroidアプリケーションのUIを持つ構成要素
- レイアウトファイル(XML)と関連付けられる
- 明確に定義されたライフサイクルを持ち、画面回転などの設定変更時に再作成される
- システムはActivityをバックスタックで管理し、ユーザーのナビゲーション履歴を維持する
Activityの例
|
|
マニュフェスト
|
|
ライフサイクルの状態遷移図
Activityのライフサイクル
アプリ起動
Androidのホーム画面からアプリのアイコンをクリックするとアプリが起動し、最初のアクティビティが画面上に表示される。
「アクティビティが開始」されると次の3つのメソッドが実行される。
onCreate()
onStart()
onResume()
その後、「実行中」の状態になる。
別のアクティビティを開始
同じアプリの別のアクティビティが開始されようとしたり、別のアプリのアクティビティが開始されようとすると、元のアクティビティは他のアクティビティによって見えなくなる。
この時、別のアクティビティが画面に表示される前に「onPause()
」メソッドが呼び出さる。
- 元のアクティビティが再び画面に表示される場合
- 右のルートを通って「
onResume()
」メソッドが呼ばれた上で「実行中」の状態に戻る
- 右のルートを通って「
- 新しいアクティビティが画面に表示され元のアクティビティが見えなくなった場合
- 下のルートを通って「
onStop()
」メソッドが呼ばれて「停止中」の状態となる
- 下のルートを通って「
再び表示される時
アクティビティは他のアクティビティの裏に隠れて表示されていない状態でも終了してはいない(停止の状態のまま)。
ユーザーによって非表示の状態から再び画面に表示されようとした場合次の3つのメソッドを実行した後に「実行中」になる。
onRestart()
onStart()
onResume()
ただし、停止中でもアクティビティは終了はしていないが、Androidのメモリが足りなくと、メモリを確保するために実行中でないアクティビティが強制的に終了となる場合がある。
この場合、アクティビティはいったん終了する。この状態からユーザーが再びアクティビティを表示させようとした場合は「onCreate()
」メソッドから改めて呼び出されることになる。
アクティビティの終了
アクティビティが終了する場合には最後に「onDestroy()
」メソッドが呼ばれて終了する。
いつActivityは落ちるのか
結論、AndroidアプリはOSの都合で勝手に終了する。
|
|
上のアプリのログ。
|
|
- つまり、Activity が破棄された後もカウントアップが続いてる
- アプリ内の全Activityが破棄されたからといって、すぐにアプリのプロセスが終了するわけではない
ではいつアプリがいつ死ぬのか?
|
|
つまり、Activity が残っているかどうかに関係なく、画面表示されていないアプリ(=フォアグラウンドな ActivityやService がないアプリ)のプロセスは、いつkill されてもおかしくないということ。
Service
Serviceとは
- Serviceはアプリケーションがバックグラウンドで長時間実行する処理を実装するためのコンポーネント
- あくまで画面のない、Userとの対話で動かないActivityという理解が正しい
- なぜなら、Service 自体はバックグラウンドスレッドではなくメインスレッドで実行されるから
特徴
- バックグラウンド処理
- Activityとは異なり、ユーザーインターフェースがない
- そのため、ユーザーの操作に依存しないバックグラウンド処理を行うことができる
- 長時間実行
- タスクの完了まで長時間実行し続けることが可能
- 例として、音楽プレーヤーやデータのダウンロード・アップロードなどがある
Serviceの種類
- Started Service
-startService()メソッドで開始されるサービス
- このサービスは、タスクが完了するまでバックグラウンドで実行される
- タスクが完了した後に
stopSelf()
やstopService()
メソッドを呼び出して停止する必要がある - 一定の時間ごとに何らかの処理を行う場合
- Bound Service
bindService()
メソッドを使用して他のアプリケーションコンポーネントにバインドされるサービス- このタイプのサービスは、クライアントと対話するためにインターフェースを提供する
- すべてのクライアントがバインドを解除するとサービスは停止する
- 他のアプリケーションコンポーネント(例: Activity)と対話しながら、定期的なタイマー処理を行う場合
- Foreground Serviceとは
- Foreground Serviceとは、通常のサービスと違い、通知を表示し、バックグラウンドで実行している事をユーザに認識させた状態で実行するService
- Foreground serviceが動いている間はサービスがシステムのリソースを消費し続けている事実をユーザーに認識させるために、専用の通知を通知領域に表示し続ける必要がある
Serviceの実装例
|
|
Serviceのライフサイクル
次の2系統がある。
- Started
startService()
メソッドで開始され、停止されるまで実行され続ける
- Bound
bindService()
メソッドで他のコンポーネントにバインドされ、バインドが解除されるまで実行される
Intent
Intentとは
- Web敵に言うと、Itentはハイパーリンクみたいなもの
- さらに、インテントは、アクティビティやサービスの開始、ブロードキャストの送信など、より広範な機能を持つ
Explicit Intent(明示的インテント)
|
|
Implicit Intent(暗黙的インテント)
|
|
Intentの例
|
|
Intentが必要な理由
- AndroidでActivityとServiceやViewModelが通信するのにIntentを使うのは、結局コンポーネントが別々のライフサイクルを持っている事に起因する
- コンポーネントがかってに作られたり消されたりしたときに、直接参照を持つとメモリーリークになる
- 故に、メッセージパッシングで通信するためにIntentなどを使って疎結合に通信する
Context
Contextとは
- Contextは、アプリケーションやアクティビティのライフサイクルを管理する抽象クラス
- ActivityもApplicationもContextクラスを継承している
Contextは3つの種類がある。
- Application Context
- アプリケーションのライフサイクル全体に関連している
- アプリケーション全体にわたるリソースやクラスへのアクセスを提供する
- 通常、getApplicationContext()メソッドで取得する
- Activity Context
- 特定のアクティビティに関連している
- そのアクティビティのライフサイクルに依存する
- 通常、アクティビティ内でthisを使用して取得する
- Service Context
- 特定のサービスに関連している
- そのサービスのライフサイクルに依存する
- 通常、サービス内でthisを使用して取得する
Contextの注意点
- メモリリークの回避
- 長時間保持されるオブジェクト(例えば、静的フィールドやシングルトン)にActivity Contextを保持すると、
- アクティビティが破棄されてもガベージコレクションされず、メモリリークの原因となる
- この場合、Application Contextを使用することが推奨される
- 適切なコンテキストの選択
- アクティビティ固有の操作(例えば、UI操作やダイアログの表示など)にはActivity Contextを使用するのが良い
- アプリケーション全体に影響を与える操作にはApplication Contextを使用するのが一般的
ContextとIntent
- Intent
- アプリケーション内やアプリケーション間で動作を開始するためのメカニズムを提供するオブジェクト
- Context
- アプリケーション環境に関する情報を提供するインターフェース
- アプリケーションのリソースやクラスにアクセスするためのメソッドを提供する
ContextはIntentを使用してアクティビティやサービスを起動するためのメソッドを提供する。
|
|
Fragment
Fragmentとは
- Fragmentは、アクティビティ内で再利用可能なUIコンポーネント
- 複数の画面サイズに対応するレイアウトを作成する際に特に有用
Fragmentの特徴
- モジュール性:UIの一部を再利用可能なコンポーネントとして定義できる
- ライフサイクル:独自のライフサイクルを持ち、アクティビティのライフサイクルと連動する
- 状態保持:構成変更(画面回転など)時にも状態を保持できる
- 通信:ホストアクティビティや他のフラグメントと通信が可能
Fragmentの例
Fragmentクラスの定義。
|
|
アクティビティでのフラグメントの使用の例。
|
|
Broadcast Receiver
Broadcast Receiverとは
Broadcast Receiverは、システム全体やアプリケーション間でのメッセージ(ブロードキャスト)の送受信を可能にするもの。
主な役割
- システムイベントやアプリケーションイベントを受信する
- バックグラウンドで動作し、特定のイベントが発生したときに反応する
使用例
- デバイスの起動完了通知
- バッテリー残量の変化
- ネットワーク接続状態の変化
- アプリのアップデート完了
- 時間帯の変更
- 言語設定の変更
- カスタムイベントの送受信
Broadcast Receiverの例
コード例
|
|
AndroidManifest.xml
|
|
使用例
|
|
Content Provider
Content Providerとは
- Content Providerは、アプリ間でのデータ共有を可能にする重要なコンポーネント
- AndroidでDBにデータを取得/保存する時に利用するクラス
- あるアプリが持っているデータを他のアプリも使用できるようになったりする
- もともと用意されているものとしては、着信ログや電話帳、ブラウザのブックマークなど
URI
- データは Uniform Resource Identifier (URI) を通じてアクセス
- Content ProviderのURIは3つの要素から構成されている
(例) content://packagename.providername/sample
- prefix:“content://”
- authority(パッケージ名+任意のprovider名):“packagename.providername”
- table:“sample”
Content Providerの例
連絡先プロバイダー
|
|
Application
Applicationとは
ApplicationクラスはAndroidアプリケーションのライフサイクル全体を管理するコンポーネント。
次の特徴を持つ。
- アプリケーション全体の基本クラス
- アプリの他のすべてのコンポーネントよりも先に作成される
- アプリケーションプロセスが存在する限り、単一のインスタンスとして維持される
主な用途:
- アプリケーション全体で共有されるグローバルな状態の管理
- アプリケーション起動時の初期化処理
- アプリケーション全体で使用されるリソースの管理
Applicationの主要メソッド
- onCreate(): アプリケーション起動時に一度だけ呼ばれる
- onTerminate(): アプリケーション終了時に呼ばれる(エミュレータでのみ動作)
- onLowMemory(): システムのメモリが少なくなった時に呼ばれる
- onTrimMemory(): システムがメモリを解放する必要がある時に呼ばれる
Applicationの例
|
|
マニュフェスト
|
|
使用例
|
|
NOTE:
- applicationはContextのプロパティ
- MainActivityはContextを継承している
- 故に、applicationにアクセスできる
コンポーネント間通信
Android IPCの方法
AndroidのIPCの仕組みは2つある。
- Binder
- 同一プロセス内のサービスとクライアント間の通信を簡単にするためのメカニズム
- AIDL(Android Interface Definition Language)
- 異なるプロセス間での通信をサポートするためのメカニズム
Binderの例
サービスの作成。
|
|
クライアントからサービスにバインド。
|
|
通信手段の比較
以下に、通信手段を比較した表を示す。
- Binder
- 同一プロセス内での直接通信に適している
- 例: アプリ内のサービスとアクティビティ間の通信
- AIDL
- 異なるプロセス間の複雑な通信に適している
- 例: サービスとクライアントが異なるアプリで動作する場合
- Messenger
- シンプルなメッセージベースの通信
- 例: サービスがバックグラウンドで動作し、アクティビティに結果を通知する場合
- BroadcastReceiver
- 一方向の非同期通信に適している
- 例: システムイベント(ネットワーク状態の変化、バッテリーの低下)の通知
- ContentProvider
- 永続データの共有に適している
- 例: 連絡先データベース、メディアストア
- Shared Preferences
- 小規模なデータ共有に適している
- 例: ユーザー設定、アプリの状態保存
- LiveData
- ライフサイクル対応のデータホルダーで、UIとデータの同期を簡素化する(同期)
- 例: ViewModelからアクティビティやフラグメントへのデータ通知
- EventBus
- アプリ内の疎結合なコンポーネント間通信
- 例: フラグメント間でのデータやイベントのやり取り
- Intent
- コンポーネント間通信(同期)
- 例: 新しいアクティビティを開始する、サービスを開始する
- JobScheduler
- バックグラウンドでのジョブスケジューリング
- 例: ネットワークが利用可能なときにデータを同期するジョブ
- WorkManager
- 信頼性の高いバックグラウンドジョブ
- 例: 定期的にサーバーとデータを同期する
- Socket通信
- リアルタイム通信
Android Jetpack
Android Jetpackとは
Android Jetpackは、Googleが提供する一連のライブラリ、ツール、およびガイドラインのコレクション。
- Foundation
- コアのライブラリ(AppCompat、Android KTX、Testなど)を含み、アプリの互換性やテストを容易にする
- Architecture
- アプリの設計を助けるライブラリ(ViewModel、LiveData、Room、DataBindingなど)で、データの管理やUIの更新を簡素化する
- Behavior
- ユーザーインターフェイスとユーザーの相互作用を向上させるライブラリ(Navigation、Paging、WorkManagerなど)を含む
- UI
- 洗練されたユーザーインターフェースの構築を助けるライブラリ(RecyclerView、Fragment、Layout、Animationsなど)を提供する
Android JetpackとJetpack Composeの違い
- Android Jetpackはアプリ全体の開発をサポートする包括的なツールセット
- Jetpack Composeは、Googleが提供する最新のUIツールキット
Jetpack Composeとは
- 元々AndroidはActivityとXMLレイアウトファイルで構成されていた
- ActivityはUIロジックを管理し、XMLファイルはUIレイアウトを定義していた
- Jetpack Composeは、XMLファイルを使用せずにKotlinコードのみでUIを定義できるようにした
Composable関数
Composable関数とは
Composable関数は、Jetpack Composeを使用してUIを構築するための基本的な構成要素
これらの関数は、宣言的なUIフレームワークであるJetpack Composeの一部で、UIコンポーネントを作成するために使用する
Composable関数の特長
- 宣言的アプローチ
- Composable関数はUIの状態を宣言的に定義する
- UIは状態に基づいて自動的に再描画されるため、UIの更新が簡単に管理できる
- 再利用可能
- Composable関数は再利用可能なUIコンポーネントを作成するために使用される
- これにより、UIの一貫性を保ち、コードの重複を減らすことができる
- 状態管理
- Composable関数は状態を持つことができ、その状態に基づいてUIを動的に変更できる
- Jetpack Composeは状態の変更を検知してUIを再描画する
- 宣言的アプローチ
Composable関数の例
Composable関数の呼び出し
|
|
Composable関数の定義
|
|
rememberとは
rememberはJetpack Composeにおける状態の管理方法。
- rememberは、Composeがコンポジションの間に値を記憶しておくために使用する
- これにより、再コンポーズ時に値がリセットされないようにする
例
|
|
- mutableStateOf
- mutableStateOfは、Composeで状態を保持するためのクラス
- 状態が変更されると、Composeはその変更を検知し、自動的にUIを再コンポーズする
- by
- byキーワードは、Kotlinのデリゲーションプロパティを使用して、プロパティのゲッターとセッターをカスタマイズする
- remember { mutableStateOf(false) }の結果を直接shouldRestartTimerとして扱えるようにする
ViewModel
ViewModelとは
- ViewModelは、UI関連のデータを保存し管理するためのクラス
- ActivityやFragmentのライフサイクルとは独立して動作する
目的
- UI関連のデータをライフサイクルの変更(画面回転など)から保護する
- ビジネスロジックをUIコントローラー(ActivityやFragment)から分離する
ライフサイクル
- ViewModelは、関連するUIコンポーネント(ActivityやFragment)が完全に破棄されるまで存在し続ける
- 画面回転などの設定変更では破棄されない
注意
- ViewModelはあくまくでViewのModel
- ViewModelでServiceの状態まで管理するのは得策ではない
- ViewModelにServiceの状態を伝えたかったらBinderを使う
ViewModelの利用例
ViewModelの定義
|
|
Composable関数の定義
|
|
Activityの例
|
|
ViewModelを使わないと
もしViewModelを使わずActivityのPrivateメンバにデータを保存すると、画面を回転させるとActivityが再度生成されるので、データが保持されず、リセットされる。
|
|
AndroidのScope
Scopeとは
- AndroidのScopeは、主にKotlin Coroutinesと関連して使用される概念
- Scopeは非同期処理の範囲を定義し、管理するために使用される
Scopeの目的は以下。
- リソース管理
- Scopeが終了すると、その中で実行中のすべてのCoroutineがキャンセルされる
- メモリリーク防止
- ライフサイクルに紐づくことで、不要になった処理を自動的に停止
- 構造化並行性
- 関連する非同期処理をグループ化し、管理を容易にする
Scopeの種類
- CoroutineScope
- 一般的なScope
- 自由に定義可能
- ViewModelScope
- ViewModelのライフサイクルに紐づく
- publicプロパティ
- LifecycleScope
- ActivityやFragmentのライフサイクルに紐づく
- publicプロパティ
Scopeの例
使用例
|
|
キャンセル処理
|
|
scope.launch
- Kotlin の coroutine を使用するための構文
- scope は CoroutineScope のインスタンス
- launch は coroutine を開始するための関数
- scope.launch { … } は、指定されたスコープ内で新しい coroutine を開始
scope.launch を使用する主な理由は以下:
- 非同期処理: UI スレッドをブロックせずに、時間のかかる処理を実行
- 構造化並行性: coroutine は階層的に管理され、親 coroutine がキャンセルされると、その子 coroutine も自動的にキャンセルされる
例えば、下の操作は非同期で実行されるため、UI スレッドをブロックせずに音を再生し、音声入力を促すことができる。
|
|
Jetpack Room
Jetpack Roomとは
Jetpack Roomは、Android開発においてSQLiteデータベースの操作を簡素化するための永続性ライブラリ。
次の利点がある。
- SQLiteの低レベルAPIを直接扱う必要がない
- コンパイル時のSQL検証
- 非同期処理との連携が容易
- データベース操作のボイラープレートコードを削減
Jetpack Roomの例
EntityとDaoの定義して非同期でアクセスする。
|
|
使用方法
|
|
WorkManager
WorkManagerとは
- WorkManagerは、延期可能な非同期タスクを簡単にスケジュールするためのAPIを提供する
- バックグラウンドで実行する必要がある作業に適している
WorkManagerの例
|
|
LiveData
LiveDataとは
- LiveDataは観測可能なデータホルダークラス
- ライフサイクルを意識したデータ保持の仕組みを提供し、主にUIとデータの同期に使用される
主な特徴:
- ライフサイクル認識:ActivityやFragmentのライフサイクルに応じてデータの更新を管理する
- メモリリーク防止:ライフサイクルが終了すると自動的に購読を解除する
- 常に最新のデータ:設定変更(画面回転など)後も最新のデータを保持する
- UIとの一貫性:メインスレッドでデータ更新を行う
LiveDataの例
LiveDataの定義
|
|
LiveDataの利用
|
|
LifecycleOwner
LifecycleOwnerとは
- LifecycleOwner は Android Jetpack の Lifecycle コンポーネントの一部
- オブジェクトのライフサイクル状態を持つクラスを表すインターフェース
- つまり、MainActivityやServiceなどのコンポーネントの状態を抽象化したものがLifecycleOwner
目的
- コンポーネントのライフサイクル状態を観察可能にする
- ライフサイクルに応じた処理を簡単に実装できるようにする
ライフサイクル状態
INITIALIZED
CREATED
STARTED
RESUMED
DESTROYED
LifecycleOwnerの例
- 以下の例では、MyLocationTrackerは具体的なActivityやFragmentに依存せず、LifecycleOwnerインターフェースを通じてライフサイクルに応じた処理を行っている
- つまり、これにより、同じMyLocationTrackerをActivity, Fragment, Serviceなど、LifecycleOwnerを実装する任意のコンポーネントで再利用できる
|
|
参考文献
- versionCodeとversionNameの 違い | アプリ開発のお勉強! アプリリ
- 「null安全」とは――Javaプログラマーが血と汗と涙を流さなくてすむ理由:Android Studioで始めるKotlin入門(3)(2/2 ページ) - @IT
- Android | アクティビティのライフサイクル
- Context | Android Developers
- ANR | App quality | Android Developers
- Android に処理を完遂させる #非同期処理 - Qiita
- 【Android & Kotlin】2次元配列で確保したデータクラスをインデックス(添字)でアクセスしてみた | プログラマーそそたた
- Android - Services
- Services in Android with Example - GeeksforGeeks
- 5分でわかるKotlin Coroutines Flow - Speaker Deck
- KotlinのGenerics、in outについて理解する - アプリ開発備忘録
- kotlin coroutinesのFlow, SharedFlow, StateFlowを整理する - Blog - Mori Atsushi
- Thread vs. Coroutines: Choosing the Right Concurrency Approach in Kotlin Android | by kmDev | Medium