Сценарий
Я реализовал виджет приложения для Android.
Щелчок по виджету запустит трансляцию с помощью PendingIntent.getBroadcast(...)
.
Я хочу сделать сетевой запрос внутри onReceive
широковещательного приемника.
(Вы спросите, почему бы мне не использовать PendingIntent.getService(...)
и не запустить IntentService
? Ну, это естественная идея, но, к сожалению, из-за фоновых ограничений служба не может быть запущена, если приложение не находится на переднем плане. Вы можете взглянуть на этот пост.)
Проблема
Чтобы доказать, что это работает, я реализовал образец BroadcastReceiver:
class WidgetClickBroadcastReceiver : BroadcastReceiver() {
override fun onReceive(context: Context?, intent: Intent?) {
if (context == null || intent == null) return
Log.i("Sira", "onReceive called")
val pendingResult = goAsync()
Observable.just(true).delay(3, TimeUnit.SECONDS)
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe {
Log.i("Sira", "Fake completion of network call")
pendingResult.finish()
}
}
}
Да, это работает.
Однако я заметил, что если я нажму на виджет несколько раз, будет создано несколько трансляций и поставлено в очередь одна за другой, пока не будет вызвана предыдущая pendingResult.finish()
.
Это можно объяснить документацией goAsync()
:
Имейте в виду, что работа, которую вы делаете здесь, будет блокировать дальнейшие трансляции до тех пор, пока она не будет завершена, поэтому чрезмерное использование этого может быть контрпродуктивным и привести к более медленному получению более поздних событий.
Итак, я хочу знать, есть ли способ предотвратить многократное срабатывание одной и той же трансляции, если она уже находится в очереди?
Или любой другой способ предотвратить вызовы в очереди из-за сумасшедших кликов по виджету?
SharedPreferences
для хранения своего состояния и проверять его перед запуском действия 19.12.2018onReceive
вызывается только после завершения предыдущего, лол. 19.12.2018