GlanceAppWidget を管理、更新する

以降のセクションでは、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 を使用して、ウィジェットのコンテンツの更新をリクエストできます。GlanceAppWidget 状態の管理セクションで説明したように、アプリ ウィジェットは別のプロセスでホストされます。Glance はコンテンツを実際の RemoteViews に変換してホストに送信します。コンテンツを更新するには、Glance が RemoteViews を再作成して再度送信する必要があります。

更新を送信するには、GlanceAppWidget インスタンスの update メソッドを呼び出し、contextglanceId を指定します。

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 コルーチンをご覧ください。

ウィジェットを更新するタイミング

ウィジェットを直ちに更新するか、定期的に更新します。

アプリがアクティブな場合、ウィジェットはすぐに更新できます。次に例を示します。

  • ユーザーがウィジェットを操作して、アクション、ラムダ呼び出し、またはアクティビティを起動するインテントをトリガーしたとき。
  • ユーザーがフォアグラウンドでアプリを操作しているとき、または Firebase Cloud Messaging(FCM)メッセージやブロードキャストに応答してアプリがすでに更新中のとき。

このような場合は、このガイドで説明されているように update メソッドを呼び出します。

アプリが起動していない場合、ウィジェットは定期的に更新できます。次に例を示します。

  • updatePeriodMillis を使用して、ウィジェットを 30 分に 1 回まで更新します。
  • WorkManager を使用して、15 分ごとなど、より頻繁な更新をスケジュールします。
  • ブロードキャストに応じてウィジェットを更新します。

リソース