Безопасно ли использовать Coroutines runBlocking() внутри onDataSetChanged RemoteViewsFactory?

Я пытаюсь получить несколько последних изображений фильмов и отобразить их в виджетах приложений для Android. Согласно требованию, виджет должен обновляться каждый час, чтобы получать последние изображения фильмов.

Поскольку я использую сопрограммы во всем приложении, мне нужно использовать существующие службы модернизации с функцией приостановки для получения данных.

Согласно документации Android, выполнять тяжелые операции внутри onDataSetChanged из RemoteViewsFactory безопасно. Поэтому я использую сам этот метод для извлечения данных из службы, а не из WorkManger, поскольку у него есть свои недостатки. См. здесь (https://commonsware.com/blog/2018/11/24/workmanager-app-widgets-side-effects.html)

Вызывается, когда на удаленном адаптере запускается notifyDataSetChanged(). Это позволяет RemoteViewsFactory реагировать на изменения данных, обновляя любые внутренние ссылки. Примечание: в рамках этого метода можно безопасно выполнять дорогостоящие задачи синхронно. Тем временем в виджете будут отображаться старые данные.

В приведенном ниже фрагменте кода я использую runBlocking() для выполнения блокирующего вызова модификации... В противном случае get view будет запущен до того, как данные будут получены. Это безопасно?

Примечание. Также адаптер замечается в методе onUpdate MyWidgetProvider каждый час.

      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 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 для отмены сопрограмм? есть ли лучший способ?
  3. Безопасно ли извлекать данные из сети внутри onDataSetChanged().
  4. Я не могу сделать асинхронный вызов внутри onDataSetChanged(). Так что мы все равно можем справиться без использования runBlocking()

ПРИМЕЧАНИЕ. Этот вопрос специально для реализации Android App Widget RemoteViewsFactory onDataSetChanged().

1 ответ

использоватьобласти,заблокирует поток пользовательского интерфейса.

Другие вопросы по тегам