Android Widget:RemoteViewsFactory的onDataSetChanged协程与请求安全问题
关于Android App Widget RemoteViewsFactory onDataSetChanged()的协程实现疑问
背景
我需要在Android App Widget中展示最新电影图片,要求Widget每小时刷新以获取最新数据。应用全程使用协程,需调用现有Retrofit服务的挂起函数获取数据。根据Android文档,RemoteViewsFactory的onDataSetChanged方法内可安全执行耗时操作,因此选择在此方法中从服务获取数据而非WorkManager(WorkManager在App Widget场景存在缺陷)。
Android文档说明:
当远程适配器触发notifyDataSetChanged()时调用。允许RemoteViewsFactory通过更新内部引用来响应数据变化。注意:耗时任务可在此方法内同步安全执行,期间Widget将显示旧数据。
我当前使用runBlocking()实现阻塞式Retrofit调用,避免getView在数据获取完成前触发。适配器每小时会在MyWidgetProvider的onUpdate方法中被通知更新。
代码片段
MyWidgetProvider的onUpdate方法
override fun onUpdate( context: Context, appWidgetManager: AppWidgetManager, appWidgetIds: IntArray ) { .... appWidgetManager.notifyAppWidgetViewDataChanged(appWidgetId, R.id.listViewMovies) ..... }
MyRemoteViewsFactory实现
class MyRemoteViewsFactory : RemoteViewsFactory { private var job: Job? = null private var data: List<Movie>? = null private val service: MovieService = ... // 初始化Retrofit服务 override fun onDataSetChanged() { try { fetchFromServer() } catch (e: Exception) { clear() } } private fun fetchFromServer() = runBlocking { job = launch { service.getMovieList().also { data = it } } } private fun clear() { job?.cancel() job = null data = null log("Cleared") } override fun onDestroy() { clear() } // 其他必要的RemoteViewsFactory方法(如getCount、getViewAt等)实现... }
日志信息
控制台日志显示onDestroy()在不同Binder线程被调用:
onCreate _main 1 _Binder:11940_5 2 _Binder:11940_5 ... onDestroy _Binder:11940_2 Clear called _Binder:11940_2
疑问
- 在
onDataSetChanged方法内使用runBlocking是否安全? - 在
runBlocking内创建嵌套协程以取消协程是否安全?有无更优方案? - 在
onDataSetChanged内进行网络请求是否安全? - 无法在
onDataSetChanged内进行异步调用,有无无需使用runBlocking的处理方式?
内容的提问来源于stack exchange,提问作者Jess
相关产品推荐
相关产品推荐

