以降のセクションでは、GlanceAppWidget
を更新してその状態を管理する方法について説明します。
GlanceAppWidget
の状態を管理する
提供された GlanceAppWidget
クラスは、ウィジェットが作成されるか更新が必要になるたびにインスタンス化されるため、ステートレスかつパッシブである必要があります。
状態の概念は、次のように分類できます。
- アプリの状態: ウィジェットが必要とするアプリの状態またはコンテンツ。たとえば、ユーザーが定義した保存先(データベース)のリストなどです。
- スナップショット状態: アプリ ウィジェットにのみ関連し、必ずしもアプリの状態を変更する、または影響を及ぼさない特定の状態。たとえば、ウィジェットでチェックボックスが選択された、カウンタが増えた、などです。
アプリケーションの状態を使用する
アプリ ウィジェットはパッシブでなければなりません。各アプリは、データレイヤを管理し、アイドル状態、読み込み状態、ウィジェット UI に表示されるエラーなどの状態を処理します。
たとえば、次のコードは、リポジトリ レイヤのメモリ内キャッシュからデスティネーションを取得し、保存されているデスティネーションのリストを提供し、その状態に応じて異なる UI を表示します。
class DestinationAppWidget : GlanceAppWidget() { // ... @Composable fun MyContent() { val repository = remember { DestinationsRepository.getInstance() } // Retrieve the cache data everytime the content is refreshed val destinations by repository.destinations.collectAsState(State.Loading) when (destinations) { is State.Loading -> { // show loading content } is State.Error -> { // show widget error content } is State.Completed -> { // show the list of destinations } } } }
状態またはデータが変更されるたびに、アプリがウィジェットに通知して更新します。詳しくは、GlanceAppWidget を更新するをご覧ください。
GlanceAppWidget
を更新します
GlanceAppWidget
の状態を管理するで説明したように、アプリ ウィジェットは別のプロセスでホストされます。Glance は、コンテンツを実際の RemoteViews
に変換してホストに送信します。コンテンツを更新するには、Glance は RemoteViews
を再作成して、もう一度送信する必要があります。
アップデートを送信するには、GlanceAppWidget
インスタンスの update
メソッドを呼び出して、context
と glanceId
を指定します。
MyAppWidget().update(context, glanceId)
glanceId
を取得するには、GlanceAppWidgetManager
に対してクエリを実行します。
val manager = GlanceAppWidgetManager(context) val widget = GlanceSizeModeWidget() val glanceIds = manager.getGlanceIds(widget.javaClass) glanceIds.forEach { glanceId -> widget.update(context, glanceId) }
または、次のいずれかのGlanceAppWidget update
拡張機能を使用します。
// Updates all placed instances of MyAppWidget MyAppWidget().updateAll(context) // Iterate over all placed instances of MyAppWidget and update if the state of // the instance matches the given predicate MyAppWidget().updateIf<State>(context) { state -> state == State.Completed }
これらのメソッドは、アプリの任意の部分から呼び出すことができます。suspend
関数であるため、メインスレッド スコープの外部で起動することをおすすめします。次の例では、CoroutineWorker
で起動しています。
class DataSyncWorker( val context: Context, val params: WorkerParameters, ) : CoroutineWorker(context, params) { override suspend fun doWork(): Result { // Fetch data or do some work and then update all instance of your widget MyAppWidget().updateAll(context) return Result.success() } }
コルーチンの詳細については、Android の Kotlin コルーチンをご覧ください。