gpt4 book ai didi

android - 从 AppWidgetProvider 启动 WorkManager 任务会导致无休止的 onUpdate 调用

转载 作者:行者123 更新时间:2023-12-04 23:47:02 25 4
gpt4 key购买 nike

我正在尝试创建一个小部件,如 this guide 中所述,

…If your widget setup process can take several seconds (perhaps while performing web requests) and you require that your process continues, consider starting a Task using WorkManager in the onUpdate() method.


但是通过将 onUpdate 中的工作请求排入队列方法,我没完没了 onUpdate大约每半秒调用一次,传入相同的 Intent 。我尝试使用 goAsync() 更新小部件和 GlobalScope.launch对于我的网络请求,它工作得很好。但是,建议使用 workmanager api 进行 i/o 工作,这就是我想要做的。
我通过 New -> Widget -> App Widget 菜单模板创建了一个应用小部件,并尝试像这样对工作进行排队:
class NewAppWidget : AppWidgetProvider() {
override fun onUpdate(context: Context, appWidgetManager: AppWidgetManager,appWidgetIds: IntArray) {
val inputData = Data.Builder().putIntArray("ids", appWidgetIds).build()
val workRequest = OneTimeWorkRequestBuilder<WidgetUpdateWorker>().setInputData(inputData).build()
WorkManager.getInstance(context.applicationContext).enqueue(workRequest)
}
}
worker :
class WidgetUpdateWorker(ctx: Context, params: WorkerParameters) : CoroutineWorker(ctx, params) {
override suspend fun doWork(): Result {
val appWidgetIds = inputData.getIntArray("ids")
val appWidgetManager = AppWidgetManager.getInstance(applicationContext)
delay(200L) // Simulate network call. The behavior is the same with Retrofit and a real network call
appWidgetIds?.forEach { id ->
val views = RemoteViews(applicationContext.packageName, R.layout.new_app_widget)
views.setTextViewText(R.id.appwidget_text, "Setting text from worker")
appWidgetManager.updateAppWidget(id, views)
}
return Result.success()
}
}
应用小部件信息 XML:
<?xml version="1.0" encoding="utf-8"?>
<appwidget-provider xmlns:android="http://schemas.android.com/apk/res/android"
android:description="@string/app_widget_description"
android:initialKeyguardLayout="@layout/new_app_widget"
android:initialLayout="@layout/new_app_widget"
android:minWidth="180dp"
android:minHeight="110dp"
android:previewImage="@drawable/example_appwidget_preview"
android:resizeMode="horizontal|vertical"
android:updatePeriodMillis="86400000"
android:widgetCategory="home_screen" />
结果,我在主屏幕上看到一个不断闪烁和更新的小部件。这也发生在模拟器和真实设备上。
我究竟做错了什么?我的目标是 API 30 并使用 WorkManager 版本 androidx.work:work-runtime-ktx:2.6.0

最佳答案

我找到了一些关于这个问题的信息,我想我现在会回答我自己的问题。
为什么会发生这种情况
根据replies on the issue tracker ,这是预期的行为。当没有待处理的工作时,WorkManager 会禁用其内部 RescheduleReceiver ,并且组件的状态更改触发 onUpdate . onUpdate然后将另一个工作请求排入队列,我们​​最终陷入无限循环。我也推荐阅读CommonsWare's post其中详细介绍了这一点。
推荐库开发人员的解决方案是不要“无条件地将工作排入 onUpdate”。这可能很难实现,而且由于我没有时间尝试这个建议,我将在下面提供一个对我有用的解决方法。
解决方法
到目前为止,我发现的最简单的解决方法是在 AppWidgetProvider 的 onEnabled 中设置一个 future 很远的虚拟工作请求。这样总有一个待处理的工作请求。例如:

override fun onEnabled(context: Context) {
val alwaysPendingWork = OneTimeWorkRequestBuilder<YourWorker>()
.setInitialDelay(5000L, TimeUnit.DAYS)
.build()

WorkManager.getInstance(context).enqueueUniqueWork(
"always_pending_work",
ExistingWorkPolicy.KEEP,
alwaysPendingWork
)
}

override fun onDisabled(context: Context) {
WorkManager.getInstance(context).cancelUniqueWork("always_pending_work")
}
不要忘记每个 AppWidgetProvider 必须提供唯一的工作名称。 "${YourWorker::class.simpleName}_work"对我来说效果很好。
也应该有可能(并且可能是一种更好的方法)使用 WorkManager 的定期工作而不是依赖小部件的更新间隔,但从我所读到的内容来看,它需要额外的、更复杂的状态管理。您也可以考虑在此处使用 JobIntentService 或 JobScheduler 代替 WorkManager。

关于android - 从 AppWidgetProvider 启动 WorkManager 任务会导致无休止的 onUpdate 调用,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/70654474/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com