簡體   English   中英

在 RemoteViewsFactory 的 onDataSetChanged 中使用協程 runBlocking() 是否安全?

[英]Is it safe to use Coroutines runBlocking() inside onDataSetChanged of RemoteViewsFactory?

我正在嘗試獲取一些最新的電影圖像並將它們顯示在 Android 應用程序小部件中,根據要求,小部件應每小時刷新一次以獲取最新的電影圖像。

由於我在整個應用程序中使用協程,我需要使用現有的 retrofit 服務和暫停 function 來獲取數據。

根據 Android 文檔,在 RemoteViewsFactory 的 onDataSetChanged 內執行繁重的操作是安全的,因此我使用此方法本身從服務而不是 WorkManger 獲取數據,因為它有其自身的缺點。 見這里( https://commonsware.com/blog/2018/11/24/workmanager-app-widgets-side-effects.html

在遠程適配器上觸發 notifyDataSetChanged() 時調用。 這允許 RemoteViewsFactory 通過更新任何內部引用來響應數據更改。 注意:在此方法中可以安全地同步執行昂貴的任務。 在此期間,舊數據將顯示在小部件中。

在下面的代碼片段中,我使用 runBlocking() 進行阻塞 retrofit 調用...否則將在獲取數據之前觸發獲取視圖。 這安全嗎?

注意:每隔一小時在 MyWidgetProvider 的 onUpdate 方法中也會注意到適配器

override fun onUpdate(
    context: Context,
    appWidgetManager: AppWidgetManager,
    appWidgetIds: IntArray
) {
   ....
   appWidgetManager.notifyAppWidgetViewDataChanged(appWidgetId, R.id.listViewMovies)
   .....
 }

代碼示例:MyRemoteViewsFactory:RemoteViewsFactory {

override fun onDataSetChanged() {
  try {
     fetchFromServer()
  } catch (e: Exception) {
    clear()      
  }
}

private fun refreshData() = runBlocking {
 job = launch {
     service.getMovieList?.also {
       data = it
     }
   }
}

private fun clear(){
    job?.cancel()
    job = null
    data = null
    log("Cleared")
}

 override fun onDestroy() {
    clear()
 }

所以我的查詢:

  1. 在 onDataSetChanged 方法中使用 runBlocking 是否安全?
  2. 在 runBlocking 中創建嵌套協程以取消協程是否安全? 有沒有更好的方法?
  3. 在 onDataSetChanged() 中從網絡中獲取數據是否安全。
  4. 我無法在 onDataSetChanged() 內部進行異步調用。所以無論如何我們可以在不使用 runBlocking() 的情況下進行處理

注意:這個問題專門針對 Android App Widget RemoteViewsFactory onDataSetChanged() 實現。

使用viewModel/lifeCycle范圍, runBlocking將阻塞 UI 線程。

1- 在 onDataSetChanged 方法中使用 runBlocking 是否安全?

3- 從 onDataSetChanged() 內部的網絡獲取數據是否安全。

文檔特別指出“可以在此方法中安全地同步執行昂貴的任務。在此期間,舊數據將顯示在小部件中。”

所以問題 1 和 3 的答案是肯定的,在那里使用runBlocking並進行網絡調用是可以的。

2- 在 runBlocking 中創建嵌套協程以取消協程是否安全? 有沒有更好的方法?

這樣做可能沒有真正的理由,因為runBlocking阻塞線程,直到子協程完成,所以在工作完成之前你不會將控制權交還給調用者。 看下一個問題。

4-我無法在 onDataSetChanged() 中進行異步調用。所以無論如何我們可以在不使用 runBlocking() 的情況下進行處理

如果您想啟動以后可以取消的協程(如果同時使用onDataSetChangedclear - 這還有待確認),您應該聲明一個CoroutineScope (作為您的類的屬性)並使用該 scope 啟動協程而不是使用runBlocking ,然后在適當的時候/在適當的時候取消 scope。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM