管理和更新 GlanceAppWidget

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

管理 GlanceAppWidget 状态

每当创建或需要更新 widget 时,系统都会实例化提供的 GlanceAppWidget 类,因此该类应为无状态且被动。

状态的概念可以分为以下几类:

  • 应用状态:微件所需的应用状态或内容。例如,用户定义的已存储目的地(即数据库)列表。
  • Glance 状态:仅与应用 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 请求更新微件内容。如管理 GlanceAppWidget 状态部分中所述,应用 widget 托管在其他进程中。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 协程。

何时更新 widget

立即或定期更新微件。

当应用处于唤醒状态时,微件可以立即更新。例如:

  • 当用户与微件互动,触发操作、lambda 调用或启动 activity 的 intent 时。
  • 当用户在前台与您的应用互动时,或者当应用已在响应 Firebase Cloud Messaging (FCM) 消息或广播进行更新时。

在这些情况下,请按照本指南中的说明调用 update 方法。

当应用未唤醒时,widget 可以定期更新。例如:

  • 使用 updatePeriodMillis 更新 widget,更新频率最高为每 30 分钟一次。
  • 使用 WorkManager 可安排更频繁的更新,例如每 15 分钟更新一次。
  • 更新微件以响应广播。

资源