Android Glance Widget无法更新:onUpdate触发但provideGlance不执行
Android Glance Widget 更新异常排查与修复
你遇到的问题是:Glance Widget的onUpdate方法已被调用,但GlanceAppWidget的provideGlance方法并未执行,仅在应用启动或间隔一段时间后才会触发更新。提供的TodayWidgetReceiver代码如下:
class TodayWidgetReceiver : GlanceAppWidgetReceiver() { override val glanceAppWidget: GlanceAppWidget get() = TodayWidget() override fun onUpdate(context: Context, appWidgetManager: AppWidgetManager, appWidgetIds: IntArray) { super.onUpdate(context, appWidgetManager, appWidgetIds) runBlocking { appWidgetIds.forEach { val glanceId = GlanceAppWidgetManager(context).getGlanceIdBy(it) glanceAppWidget.apply { updateAppWidgetState(context, glanceId) { prefs -> prefs[stringPreferencesKey("TOKEN")] = Random.nextULong().toString() } } glanceAppWidget.update(context, glanceId) } } } }
问题原因分析
- 重复更新逻辑冲突:调用
super.onUpdate()会触发Glance框架默认更新流程,后续手动调用updateAppWidgetState和update会导致状态更新与UI刷新时机冲突。 - 主线程阻塞:
runBlocking在广播接收器中使用会阻塞主线程,系统会限制广播执行时长,可能直接取消后续UI更新操作。 - 状态更新未正确触发渲染:手动更新状态后,可能未正确通知框架触发
provideGlance重新执行。
修复方案
移除
super.onUpdate()调用
Glance框架的GlanceAppWidgetReceiver已封装默认更新逻辑,重写onUpdate后手动处理更新即可,无需调用父类方法避免冲突:override fun onUpdate(context: Context, appWidgetManager: AppWidgetManager, appWidgetIds: IntArray) { // 移除super.onUpdate() CoroutineScope(Dispatchers.IO).launch { appWidgetIds.forEach { val glanceId = GlanceAppWidgetManager(context).getGlanceIdBy(it) glanceAppWidget.updateAppWidgetState(context, glanceId) { prefs -> prefs[stringPreferencesKey("TOKEN")] = Random.nextULong().toString() } glanceAppWidget.update(context, glanceId) } } }替换
runBlocking为非阻塞协程
使用CoroutineScope(Dispatchers.IO)执行异步操作,避免阻塞主线程,保证广播接收器能快速完成执行。确保
provideGlance依赖状态变化
检查TodayWidget类是否在provideGlance中正确读取状态,只有状态变化时才会触发UI更新:class TodayWidget : GlanceAppWidget() { override suspend fun provideGlance(context: Context, id: GlanceId): GlanceTheme { val prefs = currentState(context, id) val token = prefs[stringPreferencesKey("TOKEN")] ?: "" return GlanceTheme { Text(text = "Token: $token") } } }根据状态变化决定是否更新
updateAppWidgetState会返回布尔值表示状态是否变更,可据此避免不必要的UI刷新:val stateChanged = glanceAppWidget.updateAppWidgetState(context, glanceId) { prefs -> prefs[stringPreferencesKey("TOKEN")] = Random.nextULong().toString() } if (stateChanged) { glanceAppWidget.update(context, glanceId) }
内容的提问来源于stack exchange,提问作者Armands L.
相关产品推荐
相关产品推荐

