Glance AppWidget:声明 UI,显式触发更新 · AndroidX 源码指南
AAndroidX 源码指南
多形态设备
多形态设备 · androidx.wear.compose

Glance AppWidget:声明 UI,显式触发更新Wear 1.7.0-alpha07

用 provideGlance、持久状态与 updateAll 管理主屏小组件。

最后更新 2026-08-01

复制即用

class StatusWidget : GlanceAppWidget() {
    override suspend fun provideGlance(context: Context, id: GlanceId) {
        val initial = loadStatus(context)
        provideContent {
            StatusContent(initial)
        }
    }
}

class StatusWidgetReceiver : GlanceAppWidgetReceiver() {
    override val glanceAppWidget = StatusWidget()
}

suspend fun refreshWidgets(context: Context) {
    StatusWidget().updateAll(context)
}

声明式 UI,但不是 Compose 组件库

Glance 使用 @Composable 写法,但不是把普通 Compose UI 树直接嵌入桌面:

普通 ComposeGlance
ModifierGlanceModifier
Column/Row/BoxColumn/Row/Box(Glance 自己的)
Text/ImageText/Image(Glance 版本)
自定义绘制有限组件集合
无限 recomposition显式 update 驱动

它最终运行在 AppWidget 宿主的能力边界内,因此使用 GlanceModifier 与 Glance 自己的布局、文本和 action API,不能随意复用手机页面里的 Composable。

状态与更新时机

class StatusWidget : GlanceAppWidget() {
    override suspend fun provideGlance(context: Context, id: GlanceId) {
        provideContent {
            val status by rememberGlanceObject(key) { loadStatus(context) }
            Text(status.value)
        }
    }
}
  • provideGlance:首次渲染前加载数据。
  • provideContent:观察持久数据源。
  • 应用其他位置修改数据后:update(单个)或 updateAll(全部)。
  • 周期刷新:交给 WorkManager,不要在 composition 内启动永不结束的轮询。
// 触发单个 widget 刷新
suspend fun refreshOne(context: Context, id: GlanceId) {
    StatusWidget().update(context, id)
}

// 触发全部刷新(数据全局变化时)
suspend fun refreshAll(context: Context) {
    StatusWidget().updateAll(context)
}

常见陷阱

  • 主线程刷新update/updateAll 是挂起函数,记得放后台协程。
  • 在 composition 里轮询:AppWidget 宿主生命周期不由你控制,轮询会泄漏。
  • 复用普通 Composable:Glance 组件集有限,别 import 手机版组件。
  • 忘注册 ReceiverGlanceAppWidgetReceiver 必须在 manifest 声明。

要点

  • GlanceAppWidget.provideGlance 声明 UI;GlanceAppWidgetReceiver 注册入口。
  • 先加载数据再 provideContent;数据变化显式 update/updateAll
  • 周期刷新用 WorkManager;composition 内不轮询。
  • 运行在 AppWidget 宿主边界内,组件集有限。

相关页面