Безопасно ли использовать 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
Итак, мои запросы:
- Безопасно ли использовать runBlocking внутри метода onDataSetChanged?
- Безопасно ли создавать вложенные сопрограммы внутри runBlocking для отмены сопрограмм? есть ли лучший способ?
- Безопасно ли извлекать данные из сети внутри onDataSetChanged().
- Я не могу сделать асинхронный вызов внутри onDataSetChanged(). Так что мы все равно можем справиться без использования runBlocking()
ПРИМЕЧАНИЕ. Этот вопрос специально для реализации Android App Widget RemoteViewsFactory onDataSetChanged().
1 ответ
использовать