Android App Widget二次亮屏后倒计时UI不更新问题求助
Hey there! Let's dig into why your currency exchange widget's countdown UI gets stuck after two screen off/on cycles—even though you've confirmed the timer is running and updateAppWidget is triggered.
What's Likely Causing the Issue
The core problem is almost certainly related to reusing the same RemoteViews instance across updates. RemoteViews is a cross-process object, and reusing it can lead to stale state being cached by the system. Even if you update the text in the old RemoteViews instance, the widget host might not recognize the change as a meaningful update, especially after multiple screen state transitions.
Additionally, relying solely on the onTick callback to update the UI when the screen is on can lead to delays or missed refreshes if the system batches widget updates during screen transitions.
Fixes to Implement
Here are actionable steps to resolve the stuck UI:
Use a fresh
RemoteViewsinstance every time you update
Instead of reusing a singleRemoteViewsobject, create a new one in eachonTickcall. This ensures the system picks up the UI change immediately.Listen for screen-on broadcasts to force an immediate refresh
Register a broadcast receiver to catch theACTION_SCREEN_ONevent, then trigger a widget update right when the screen turns on. This eliminates any waiting for the nextonTickcycle.Double-check screen state detection for cross-version compatibility
Ensure yourPowerManagerlogic works reliably across all Android versions you support.
Modified Code Example
First, add a broadcast receiver to handle screen-on events:
class ScreenOnReceiver : BroadcastReceiver() { override fun onReceive(context: Context, intent: Intent) { if (intent.action == Intent.ACTION_SCREEN_ON) { // Trigger widget update immediately val appWidgetManager = AppWidgetManager.getInstance(context) val componentName = ComponentName(context, YourWidgetProvider::class.java) val appWidgetIds = appWidgetManager.getAppWidgetIds(componentName) // Call your existing update method YourWidgetProvider.updateAllWidgets(context, appWidgetManager, appWidgetIds) } } }
Register/unregister the receiver in your widget provider:
override fun onEnabled(context: Context) { super.onEnabled(context) val filter = IntentFilter(Intent.ACTION_SCREEN_ON) context.registerReceiver(ScreenOnReceiver(), filter) } override fun onDisabled(context: Context) { super.onDisabled(context) context.unregisterReceiver(ScreenOnReceiver()) }
Update your countdown logic to use fresh RemoteViews:
if (timestamp.isNotEmpty()) { countDownTimer?.cancel() countDownTimer = null val difference = DateUtils.getDifference(timestamp) countDownTimer = object : CountDownTimer(difference, 1000) { override fun onFinish() { viewModel.getPrice() // Update widget when countdown finishes val finishViews = RemoteViews(context.packageName, com.example.bipexchange.R.layout.your_widget_layout) finishViews.setTextViewText(com.example.bipexchange.R.id.countDownTV, context.getString(R.string.countdown_complete)) appWidgetManager.updateAppWidget(appWidgetId, finishViews) } override fun onTick(millisUntilFinished: Long) { val (minutesLeft, secsLeft) = DateUtils.getMinAndSecsLeft(millisUntilFinished) // Create a fresh RemoteViews instance every tick val freshViews = RemoteViews(context.packageName, com.example.bipexchange.R.layout.your_widget_layout) freshViews.setTextViewText( com.example.bipexchange.R.id.countDownTV, context.getString( com.example.bipexchange.R.string.minutesSeconds, minutesLeft, secsLeft ) ) val pm = getSystemService(context, PowerManager::class.java) val isScreenOn = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT_WATCH) { pm?.isInteractive } else { pm?.isScreenOn } if (isScreenOn == true) { appWidgetManager.updateAppWidget(appWidgetId, freshViews) } } } countDownTimer?.start() }
Why This Works
- Fresh
RemoteViews: Each update uses a new instance, so the system can't ignore the change due to cached state. - Screen-on broadcast: Ensures the widget refreshes instantly when the screen turns on, syncing the UI with the current timer state immediately.
- Robust screen detection: The version-specific
PowerManagercheck ensures you're correctly identifying when the screen is active across all supported devices.
内容的提问来源于stack exchange,提问作者Wolf Gate

