You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Jetpack Glance Widget更新求助:三种场景下的文本更新实现

Jetpack Glance Widget 动态更新解决方案

你当前代码的核心问题是:ExampleWidget的构造参数仅在ExampleWidgetReceiver初始化时执行一次,后续无法动态更新。Glance Widget的更新依赖状态管理+主动触发刷新,以下是针对三个场景的具体实现:


核心重构:用Glance状态管理动态文本

先修改ExampleWidget,不再通过构造传参,而是从Glance偏好状态中读取动态文本,同时添加点击交互:

class ExampleWidget : GlanceAppWidget() {
    companion object {
        // 定义存储文本的常量键
        const val DISPLAY_TEXT_KEY = "display_text"
    }

    @Composable
    override fun Content() {
        // 获取当前Widget的状态偏好
        val preferences = currentState<Preferences>()
        // 读取文本,默认值为初始提示
        val displayText = preferences.getString(DISPLAY_TEXT_KEY, "点击更新")

        val customTextStyle = TextStyle(
            fontWeight = FontWeight.Bold,
            fontSize = 18.sp
        )

        // 给文本添加点击事件,触发更新回调
        Text(
            text = displayText,
            modifier = GlanceModifier.clickable(actionRunCallback<UpdateWidgetCallback>()),
            style = customTextStyle
        )
    }
}

修改ExampleWidgetReceiver,去掉硬编码的构造参数:

class ExampleWidgetReceiver : GlanceAppWidgetReceiver() {
    override val glanceAppWidget: GlanceAppWidget = ExampleWidget()
}

场景1:调整Widget大小时更新

在ExampleWidgetReceiver中重写onAppWidgetOptionsChanged方法,触发Widget更新:

override fun onAppWidgetOptionsChanged(
    context: Context,
    appWidgetManager: AppWidgetManager,
    appWidgetId: Int,
    newOptions: Bundle
) {
    super.onAppWidgetOptionsChanged(context, appWidgetManager, appWidgetId, newOptions)
    val glanceId = GlanceAppWidgetId(appWidgetId)
    
    // 更新状态:设置随机字符串
    glanceAppWidget.updateAppWidgetState(context, glanceId) { preferences ->
        preferences.toMutablePreferences().apply {
            putString(ExampleWidget.DISPLAY_TEXT_KEY, getRandomString())
        }
    }
    
    // 触发Widget刷新
    glanceAppWidget.update(context, glanceId)
}

场景2:点击Widget时更新

创建ActionCallback子类处理点击后的更新逻辑:

class UpdateWidgetCallback : ActionCallback {
    override suspend fun onAction(
        context: Context,
        glanceId: GlanceId,
        parameters: ActionParameters
    ) {
        // 更新状态为随机字符串
        ExampleWidget().apply {
            updateAppWidgetState(context, glanceId) { preferences ->
                preferences.toMutablePreferences().apply {
                    putString(DISPLAY_TEXT_KEY, getRandomString())
                }
            }
            // 刷新Widget
            update(context, glanceId)
        }
    }
}

在AndroidManifest.xml中注册该回调服务:

<service
    android:name=".UpdateWidgetCallback"
    android:permission="android.permission.BIND_REMOTEVIEWS" />

场景3:每隔数分钟自动更新

推荐用WorkManager实现可靠的定时更新(适配Android后台限制):

1. 创建Worker类处理更新逻辑

class UpdateWidgetWorker(context: Context, params: WorkerParameters) : CoroutineWorker(context, params) {
    override suspend fun doWork(): Result {
        val appWidgetManager = AppWidgetManager.getInstance(applicationContext)
        val receiver = ExampleWidgetReceiver()
        // 获取所有已添加的当前Widget的ID
        val widgetIds = appWidgetManager.getAppWidgetIds(
            ComponentName(applicationContext, ExampleWidgetReceiver::class.java)
        )
        
        // 逐个更新Widget
        widgetIds.forEach { widgetId ->
            val glanceId = GlanceAppWidgetId(widgetId)
            receiver.glanceAppWidget.updateAppWidgetState(applicationContext, glanceId) { preferences ->
                preferences.toMutablePreferences().apply {
                    putString(ExampleWidget.DISPLAY_TEXT_KEY, getRandomString())
                }
            }
            receiver.glanceAppWidget.update(applicationContext, glanceId)
        }
        
        return Result.success()
    }
}

2. 在AndroidManifest.xml中注册Worker

<service
    android:name=".UpdateWidgetWorker"
    android:permission="android.permission.BIND_JOB_SERVICE" />

3. 启动/停止定时任务

在ExampleWidgetReceiver中添加启动和停止逻辑:

override fun onEnabled(context: Context) {
    super.onEnabled(context)
    // 启动每5分钟一次的定时更新
    val periodicWork = PeriodicWorkRequestBuilder<UpdateWidgetWorker>(5, TimeUnit.MINUTES)
        .build()
    WorkManager.getInstance(context).enqueueUniquePeriodicWork(
        "WidgetAutoUpdate",
        ExistingPeriodicWorkPolicy.REPLACE,
        periodicWork
    )
}

override fun onDisabled(context: Context) {
    super.onDisabled(context)
    // 所有Widget被移除时,取消定时任务
    WorkManager.getInstance(context).cancelUniqueWork("WidgetAutoUpdate")
}

关键注意事项

  • 所有更新必须先通过updateAppWidgetState修改状态,再调用update触发刷新,这是Glance更新的核心流程。
  • alpha05属于早期预览版,部分API可能后续变动,但状态管理+主动刷新的逻辑保持一致。
  • 确保getRandomString()在协程/后台线程中可以正常调用(CoroutineWorker已适配协程环境)。

内容的提问来源于stack exchange,提问作者The_F

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.25 16:22:12