首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >在onDataSetChanged of RemoteViewsFactory中使用Coroutines ()安全吗?

在onDataSetChanged of RemoteViewsFactory中使用Coroutines ()安全吗?
EN

Stack Overflow用户
提问于 2022-07-24 10:44:54
回答 2查看 260关注 0票数 3

我正在尝试获取一些最新的电影图像,并将它们显示在Android应用程序的小部件中,按照要求,小部件应该每小时刷新一次,以获取最新的电影图像。

由于我在整个应用程序中都使用协同服务,所以我需要使用现有的带有挂起功能的更新服务来获取数据。

根据Android文档,在onDataSetChanged of RemoteViewsFactory中执行大量操作是安全的,因此我使用这个方法本身从服务中获取数据,而不是WorkManger,因为它有其自身的缺点。见这里(https://commonsware.com/blog/2018/11/24/workmanager-app-widgets-side-effects.html)

在远程适配器上触发notifyDataSetChanged()时调用。这允许RemoteViewsFactory通过更新任何内部引用来响应数据更改。注意:在此方法中可以安全地安全地执行昂贵的任务。在此期间,旧数据将显示在小部件中。

在下面的代码片段中,我使用runBlocking()来进行阻塞改造调用.否则,获取数据之前将触发get视图。这安全吗?

注意:在onUpdate方法的MyWidgetProvider中,每小时都会注意到适配器

代码语言:javascript
复制
override fun onUpdate(
    context: Context,
    appWidgetManager: AppWidgetManager,
    appWidgetIds: IntArray
) {
   ....
   appWidgetManager.notifyAppWidgetViewDataChanged(appWidgetId, R.id.listViewMovies)
   .....
 }

代码示例: MyRemoteViewsFactory : RemoteViewsFactory {

代码语言:javascript
复制
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()
 }

Console log shows onDestory() s being called... but in different binder.

 onCreate _main
 1 _Binder:11940_5
 2 _Binder:11940_5
 3 _Binder:11940_5
 4 _Binder:11940_5
 5 _Binder:11940_5
 6 _Binder:11940_5
 7 _Binder:11940_5
 8 _Binder:11940_5
 9 _Binder:11940_5
 10 _Binder:11940_5

 11 _Binder:11940_5
 onDestroy _Binder:11940_2
 Clear called _Binder:11940_2

所以我的问题是:

  1. 在runBlocking中使用onDataSetChanged方法安全吗?
  2. 在runBlocking中创建嵌套的协同线以取消Coroutines安全吗?还有更好的办法吗?
  3. 从onDataSetChanged()内部的网络获取数据是否安全。
  4. 我无法在onDataSetChanged()中进行异步调用。那么,我们是否可以不使用runBlocking()来处理

注意:这个问题特别适用于Android onDataSetChanged()实现.

EN

回答 2

Stack Overflow用户

发布于 2022-07-24 11:17:47

使用viewModel/lifeCycle作用域,runBlocking将阻塞UI线程。

票数 1
EN

Stack Overflow用户

发布于 2022-07-24 17:34:12

1-在runBlocking中使用onDataSetChanged方法安全吗? 3-从onDataSetChanged()内部的网络获取数据安全吗?

文档特别指出,“在此方法中可以安全地安全地执行昂贵的任务。在此期间,旧的数据将显示在小部件中。”

所以问题1和问题3的答案是肯定的,在那里使用runBlocking并进行网络呼叫是可以的。

2-在runBlocking内创建嵌套的协同线以取消协同线安全吗?还有更好的办法吗?

这样做可能没有真正的理由,因为runBlocking会阻塞线程,直到子协同完成为止,所以在工作完成之前,您不会将控制权还给调用者。见下一个问题。

4-我不能在onDataSetChanged()中进行异步调用。那么,我们是否可以不使用runBlocking()来处理

如果您想要启动以后可以取消的协同(在同时使用onDataSetChangedclear (这还有待确认)的情况下),则应该声明一个CoroutineScope (作为类的属性),并使用该范围而不是使用runBlocking启动协同,然后在适当的时候/在适当的情况下取消该作用域。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/73097689

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档