Как да направите Android повече Rx - 5 съвета и трика

Ако използвате RxJava в ежедневието си, вероятно един ден ще стигнете до точката, в която искате да… поставите RxJava навсякъде! Нека ви дам 5 практически съвета.

Използването на RxJava навсякъде не е лоша идея (обикновено). Нормално е да мислите „Ей, ще изглежда много по-готино, ако мога просто да го вложа в потока на RxJava, вместо да използвам for-loop / Handler / Async Task / някакво друго грозно решение“. Да, ще е готино. Ако можех само ...

Е, имам някои добри новини за вас - с RxJava можете да направите повечето от нещата, за които някога сте мечтали! Позволете ми да ви дам моите 5 съвета относно нещата, които харесвам и често използвам в моите проекти.

Тези кодови фрагменти ще работят както на RxJava, така и на RxJava2. Тази статия предполага, че имате някои основни познания за RxJava. Ако не, препоръчвам ви първо да прочетете някои други статии (тази на RxJava - производствената линия - прави страхотно начало).

# 1 Откриване на двойно щракване

Имате няколко бутона в приложението си и искате да откриете дали тези бутони са щракнати два пъти. Лесно, нали? Да, всичко, което трябва да направите, е да направите брояч, да проверите за всяко щракване, да премествате брояча нагоре и не забравяйте да нулирате брояча след това ... Няма начин, трябва да има по-чист начин за това. Разбира се, ето го:

private PublishSubject  eventSubject = PublishSubject.create ();
публичен статичен финал int TIME_BETWEEN_EVENTS_MILLIS = 500;
публичен статичен краен int NUMBER_OF_EVENTS = 2;
обществен DoubleClick () {
    eventSubject
        .buffer (eventSubject.debounce (TIME_BETWEEN_EVENTS_MILLIS,
            TimeUnit.MILLISECONDS))
        .filter (събития -> events.size () == NUMBER_OF_EVENTS)
        .отпишете се (събития -> doSomething ());
    button.setOnClickListener ((бутон) ->
        eventSubject.onNext (истина));
}

С помощта на PublishSubject можем да излъчваме собствените си елементи и да ги хващаме. След улов проверяваме дали броят събития е същият като стойността, която искаме. Разбира се, можете да го направите с всяко събитие - получаване на текст от TextView, получаване на кликвания от всеки друг изглед или нещо друго.

# 2 Повтаряне на заявки към API на всеки 10 минути

Използването на оператора repeWhen, комбинирано с резултати от забавяне, може да доведе до забавяне на абонамента ни след известно време. Ако по някаква причина искате да поискате нови данни от API на всеки 10 минути, можете да го направите с RxJava само в един ред:

sourceObservable.repeatWhen (попълнен -> complete.delay (10,
    TimeUnit.MINUTES));

Имайте предвид, че наблюдаемото ще се повтори само ако предишното е завършено.

# 3 Комбиниране на два зависими обекта

Да речем, че получаваме котки от API и за всяка котка бихме искали да вземем няколко играчки (които зависят от Cat). След това искаме да имаме обект, комбиниран с CatAndToys - възможно е да направите това с RxJava, като използвате втория параметър на flatMap (това, което не се използва толкова често), който

[…] Комбинира елементи от източника Наблюдаемо с Наблюдаемото, задействано от тези изходни елементи, излъчвайки тези комбинации.

Източник: RxJava документация

Нека кодът говори сам за себе си:

Наблюдаем  catWithToysObservable =
    getCatObservable ()
        .flatMap ((cat) -> getToysForCatObservable (cat),
            (котка, играчки) -> нови CatWithToys (котка, играчки));

Виждаме този първи параметър в flatMap приема Cat като параметър и връща играчките. Тогава вторият параметър взема Cat and Toys (резултатът от първата функция) и връща обекта CatWithToys. По този начин можете да комбинирате много зависими заявки към API, без да използвате вложени оператори flatMap.

# 4 Поискайте страница

Ако искате да страницете чрез някои обекти от API, можете да го направите лесно с RxJava. Номерът е да обедините всички страници, докато не постигнете някаква крайна точка (например последната заявка ви дава празни резултати или броят на елементите ще бъде правилен и правилен). Нека да разгледаме кода:

обществено наблюдаемо <Списък <Потребител>> getAllUsers () {
    върнете getUsersObservable (null);
}
частен наблюдаем <Списък <Потребител>> getUsersObservable (окончателен низ
    lastUserId) {
    върнете apiAdapter
        .getData (lastUserId)
        .filter (userList ->! isLastPage (userList))
        .flatMap (това :: getNextPageUsersObservable);
}
частен наблюдателен <Списък <Потребител>> getNextPageUsersObservable (окончателен
    Списък  userList) {
    
    Наблюдаем <Списък <Потребител>> потребителиPageObservable =
        Observable.just (Списък);
    int lastUserId = getLastUserId (userList);
    Наблюдаем <Списък <Потребител>> nextUsersPageObservable =
        getUsersObservable (lastUserId);
    връщане Observable.merge (nextUsersPageObservable,
        usersPageObservable);
}
private boolean isLastPage (окончателен списък  userList) {
    върнете userList.isEmpty ();
}

Първо, ние искаме една страница без никакъв параметър (или можете да поставите 0 тук, в зависимост от вашия API), след това проверяваме състоянието на крайния ни списък - ако не сме стигнали до края, искаме някои нови страници с параметъра от последната заявка (може да е последният идентификатор на потребителя, или дата на най-новата снимка, или нещо друго) и ние ще го обединим с предишната наблюдаема. Ако стигнем до края на списъка, приключваме.

# 5 Лек RxBus

Ако използвате автобус за събития във вашия проект (без значение дали това е Otto, Event Bus от Greenrobot или нещо друго), може да се заинтересувате да внедрите свой собствен автобус за събития - RxBus! Може би се питате защо възобновяваме колелото, вместо да използваме нещо, направено от някой друг?

Е, когато видите колко лесно е да внедрите вашия собствен EventBus с RxJava, можете да преосмислите поставянето на това като вътрешна библиотека. Независими сте от промените във външната библиотека, така че можете да коригирате RxBus според вашите нужди и - ако вече имате RxJava в проекта - защо не го използвате за нещо повече?

публична класа RxBus {
    частен статичен краен екземпляр RxBus = нов RxBus ();
    частен окончателен Тема  rxBus;
    обществен RxBus () {
        PublishSubject  rxEventPublishSubject =
            PublishSubject.create ();
        rxBus = rxEventPublishSubject.toSerialized ();
    }
    публичен статичен RxBus getInstance () {
        връщане екземпляр;
    }
    обществено наблюдаемо  getRxBus () {
        връщане rxBus;
    }
    публичен невалиден пост (окончателен RxEvent rxEvent) {
        rxBus.onNext (rxEvent);
    }
    публична класа RxEvent {}
}

Основното „ядро“ на RxBus е SerializedSubject (много подобно на PublishSubject, което използвахме за откриване на двойни кликвания, но това е безопасно за конци). Ние просто създаваме сингъл клас, който има препратка към този SerializedSubject. Ако изпратим някакво събитие, ние излъчваме елементи с SerializedSubject, ако се абонираме за събитието, ние се абонираме за получаване на събития от SerializedSubject. Просто, нали? Използваме метода toSerialized (), защото искаме да използваме нашия RxBus от различни нишки.

заключение

Както можете да видите - има много неща, които можете да направите с RxJava. Полезно е за изгледи, заявяване на данни и вътрешна комуникация в приложението ви. Не забравяйте, че има много решения за проблемите, които представих и RxJava може да не е винаги най-добрият, но се надявам тези съвети да ви вдъхновят да потърсите други решения за вашите проблеми.

Това е! Надявам се да ви харесат моите съвети. Следете за повече!