3. Условие:
Например, у нас есть Single для получения списка комментариев и Single для публикации
комментария. Необходимо обеспечить отправку комментария после загрузки списка.
Как последовательно выполнить 2 цепи?
4. Условие:
Например, у нас есть Single для получения списка комментариев и Single для публикации
комментария. Необходимо обеспечить отправку комментария после загрузки списка.
Single.fromCallable { dataRepository.loadComments() }
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(…)
Как последовательно выполнить 2 цепи?
5. Условие:
Например, у нас есть Single для получения списка комментариев и Single для публикации
комментария. Необходимо обеспечить отправку комментария после загрузки списка.
Single.fromCallable { dataRepository.addComment(…) }
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(…)
Как последовательно выполнить 2 цепи?
6. Решение:
Использовать Semaphore из java.util.concurrent.
val semaphore = Semaphore(1)
Single.fromCallable { dataRepository.loadComments() }
.doOnSubscribe { semaphore.acquire() }
.subscribeOn(Schedulers.io())
.doFinally { semaphore.release() }
.observeOn(AndroidSchedulers.mainThread())
.subscribe(…)
Как последовательно выполнить 2 цепи?
7. Решение:
Использовать Semaphore из java.util.concurrent.
val semaphore = Semaphore(1)
Single.fromCallable { dataRepository.addComment(…) }
.doOnSubscribe { semaphore.acquire() }
.subscribeOn(Schedulers.io())
.doFinally { semaphore.release() }
.observeOn(AndroidSchedulers.mainThread())
.subscribe(…)
Как последовательно выполнить 2 цепи?
9. Какие возможности предоставляет нам такой подход?
• Потокобезопасность для цепи.
• Потокобезопасность для отдельного участка цепи.
Как последовательно выполнить 2 цепи?
10. Какие возможности предоставляет нам такой подход?
• Потокобезопасность для цепи.
• Потокобезопасность для отдельного участка цепи.
• Возможность запускать одновременно определенное количество цепей.
Как последовательно выполнить 2 цепи?
11. Какие возможности предоставляет нам такой подход?
• Потокобезопасность для цепи.
• Потокобезопасность для отдельного участка цепи.
• Возможность запускать одновременно определенное количество цепей.
• Нет необходимости объединять все цепи в одну.
Как последовательно выполнить 2 цепи?
14. Условие:
Необходимо выполнить запрос на сервер и:
• При отсутствии Интернет-соединения сразу выдать ошибку.
• При возникновении ошибки повторить запрос с задержкой в 5 секунд, не больше 3 раз.
Обрабатываем ошибки красиво
15. Условие:
Необходимо выполнить запрос на сервер и:
• При отсутствии Интернет-соединения сразу выдать ошибку.
• При возникновении ошибки повторить запрос с задержкой в 5 секунд, не больше 3 раз.
• Наложить ограничение в 1 минуту на выполнение всей операции.
Обрабатываем ошибки красиво
16. Условие:
Необходимо выполнить запрос на сервер и:
• При отсутствии Интернет-соединения сразу выдать ошибку.
• При возникновении ошибки повторить запрос с задержкой в 5 секунд, не больше 3 раз.
• Наложить ограничение в 1 минуту на выполнение всей операции.
dataRepository.requestDataFromNetwork()
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(…)
Обрабатываем ошибки красиво
27. PublishSubject
val source = PublishSubject.create<Int>()
// Получит 1, 2, 3, 4 и onComplete
source.subscribe(getFirstObserver())
source.onNext(1)
source.onNext(2)
source.onNext(3)
// Получит 4 и onComplete для следующего наблюдателя тоже
source.subscribe(getSecondObserver());
source.onNext(4)
source.onComplete()
Пример использования Subject
28. RelplaySubject
val source = ReplaySubject.create<Int>()
// Он получит 1, 2, 3, 4
source.subscribe(getFirstObserver())
source.onNext(1)
source.onNext(2)
source.onNext(3)
source.onNext(4)
source.onComplete()
// Он также получит 1, 2, 3, 4 так как он использует Replay Subject
source.subscribe(getSecondObserver())
Пример использования Subject
29. BehaviorSubject
val source = BehaviorSubject.create<Int>()
// Получит 1, 2, 3, 4 and onComplete
source.subscribe(getFirstObserver())
source.onNext(1)
source.onNext(2)
source.onNext(3)
// Получит 3(последний элемент) и 4(последующие элементы) и onComplete
source.subscribe(getSecondObserver())
source.onNext(4)
source.onComplete()
Пример использования Subject
30. AsyncSubject
val source = AsyncSubject.create<Int>()
// Получит только 4 и onComplete
source.subscribe(getFirstObserver())
source.onNext(1)
source.onNext(2)
source.onNext(3)
// Тоже получит только 4 и onComplete
source.subscribe(getSecondObserver())
source.onNext(4)
source.onComplete()
Пример использования Subject
31. Решение:
class ConnectivityReceiver(val connectivitySubject: PublishSubject<Boolean>… {
override fun onReceive(context: Context, arg1: Intent) {
connectivitySubject.onNext(isConnected())
}
private fun isConnected(): Boolean {
val connectivityManager = context.getSystemService(Context.CONNECTIVITY_SERVICE)
val activeNetwork = connectivityManager.activeNetworkInfo
return activeNetwork != null && activeNetwork.isConnected
}
}
Пример использования Subject
32. Решение:
…
override fun onStart() {
registerReceiver(connectivityReceiver,
IntentFilter(ConnectivityManager.CONNECTIVITY_ACTION))
super.onStart()
}
override fun onStop() {
unregisterReceiver(connectivityReceiver)
super.onStop()
}
…
Пример использования Subject
33. Другие примеры использования:
• Автоматическое отслеживание просмотренных элементов списка.
• Обработка нажатий (кликов) на элементы списка.
• Отображение ошибок.
• Обновление элементов.
… и многое другое.
Пример использования Subject
45. Условие:
Необходимо реализовать поиск и при изменении строки запрашивать данные с сервера.
Должны соблюдаться условия:
• Данные с сервера должны запрашиваться не чаще, чем 1 раз в 500 миллисекунд.
Реактивный поиск
46. Условие:
Необходимо реализовать поиск и при изменении строки запрашивать данные с сервера.
Должны соблюдаться условия:
• Данные с сервера должны запрашиваться не чаще, чем 1 раз в 500 миллисекунд.
• Пустые строки должны игнорироваться.
Реактивный поиск
47. Условие:
Необходимо реализовать поиск и при изменении строки запрашивать данные с сервера.
Должны соблюдаться условия:
• Данные с сервера должны запрашиваться не чаще, чем 1 раз в 500 миллисекунд.
• Пустые строки должны игнорироваться.
• Если строка была отредактирована, но ее содержимое осталось прежним, то запрос
отправляться не должен.
Реактивный поиск
48. Условие:
Необходимо реализовать поиск и при изменении строки запрашивать данные с сервера.
Должны соблюдаться условия:
• Данные с сервера должны запрашиваться не чаще, чем 1 раз в 500 миллисекунд.
• Пустые строки должны игнорироваться.
• Если строка была отредактирована, но ее содержимое осталось прежним, то запрос
отправляться не должен.
• Должен отменяться последний запрос, если строка изменилась.
Реактивный поиск
58. Решение:
…
fun getDataFromMemory() = memoryDataSource.getData()
fun getDataFromDisk() = diskDataSource.getData().doOnNext { data ->
memoryDataSource.cacheInMemory(data)
}
fun getDataFromNetwork() = networkDataSource.getData().doOnNext { data ->
diskDataSource.saveToDisk(data)
memoryDataSource.cacheInMemory(data)
}
…
Кэширование данных
59. Использование:
val memory = dataSource.getDataFromMemory()
val disk = dataSource.getDataFromDisk()
val network = dataSource.getDataFromNetwork()
Observable.concat<Data>(memory, disk, network)
.subscribeOn(Schedulers.io())
.firstElement()
.toObservable()
.observeOn(AndroidSchedulers.mainThread())
.subscribe(…)
Кэширование данных