管理和更新 GlanceAppWidget

以下部分介绍了如何更新 GlanceAppWidget 和管理其状态。

管理 GlanceAppWidget 状态

每当创建 widget 或需要更新 widget 时,提供的 GlanceAppWidget 类都会进行实例化,因此它应该是无状态的被动类

状态的概念可分为以下几个方面:

  • 应用状态:widget 所需的应用状态或内容。例如,由用户定义的存储目的地(即数据库)的列表。
  • 概览状态:仅与应用 widget 相关的特定状态,不一定会修改或影响应用的状态。例如,在 widget 中选中了复选框,或增加了计数器。

使用应用状态

应用 widget 应该是被动的。每个应用负责管理数据层和处理状态,例如空闲、正在加载和在 widget 界面中反映错误。

例如,以下代码会从代码库层从内存缓存中检索目的地,提供存储的目的地列表,并根据其状态显示不同的界面:

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
            }
        }
    }
}

每当状态或数据发生变化时,应用都要负责通知和更新 widget。如需了解详情,请参阅更新 GlanceAppWidget

更新 GlanceAppWidget

管理 GlanceAppWidget 状态部分中所述,应用 widget 托管在不同的进程中。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 协程