Cómo hacer que Android sea más Rx - 5 consejos y trucos

Si está utilizando RxJava en su rutina diaria, probablemente algún día llegará al punto en el que desea ... ¡colocar RxJava en todas partes! Déjame darte 5 consejos prácticos.

Usar RxJava en todas partes no es una mala idea (generalmente). Es normal que esté pensando "Oye, se verá mucho mejor si pudiera poner esto en el flujo de RxJava, en lugar de usar for-loop / Handler / Async Task / alguna otra solución fea". Sí, será genial. Si tan sólo pudiera…

Bueno, tengo buenas noticias para ti: ¡con RxJava puedes hacer la mayoría de las cosas que siempre has soñado! Permíteme darte mis 5 consejos sobre las cosas que me gustan y que a menudo uso en mis proyectos.

Estos fragmentos de código funcionarán tanto en RxJava como en RxJava2. Este artículo asume que tiene algunos conocimientos básicos sobre RxJava. Si no, le recomiendo que lea primero otros artículos (este en RxJava, la línea de producción, es un gran comienzo).

# 1 Detección de doble clic

Tiene algunos botones en su aplicación y desea detectar si se hizo clic dos veces en estos botones. Fácil, ¿no es así? Sí, todo lo que necesita hacer es hacer un contador, verificar cada clic, mover el contador hacia arriba y recordar restablecer el contador después ... De ninguna manera, debe haber una forma más limpia de hacerlo. Por supuesto, aquí está:

PublishSubject privado  eventSubject = PublishSubject.create ();
public static final int TIME_BETWEEN_EVENTS_MILLIS = 500;
public static final int NUMBER_OF_EVENTS = 2;
DoubleClick público () {
    eventSubject
        .buffer (eventSubject.debounce (TIME_BETWEEN_EVENTS_MILLIS,
            TimeUnit.MILLISECONDS))
        .filter (eventos -> eventos.size () == NUMBER_OF_EVENTS)
        .subscribe (eventos -> doSomething ());
    button.setOnClickListener ((botón) ->
        eventSubject.onNext (true));
}

Al usar PublishSubject, podemos emitir nuestros propios elementos y atraparlos. Después de la captura, verificamos si el número de eventos es el mismo que el valor que queremos. Por supuesto, puede hacerlo con cada evento: obtener un texto de TextView, obtener clics de cualquier otra Vista o cualquier otra cosa.

# 2 Repetir solicitudes a la API cada 10 minutos

El uso de la repetición del operador cuando, combinado con los resultados de demora, puede demorar nuestra suscripción después de un tiempo. Si, por algún motivo, desea solicitar nuevos datos de la API cada 10 minutos, puede hacerlo con RxJava en una sola línea:

sourceObservable.repeatWhen (complete -> complete.delay (10,
    TimeUnit.MINUTES));

Solo tenga en cuenta que ese Observable solo se repetirá si se completó el anterior.

# 3 Combinando dos objetos dependientes

Digamos que estamos recibiendo gatos de API, y, por cada gato, nos gustaría obtener algunos juguetes (que dependen de los gatos). Después de esto, queremos tener un objeto combinado con CatAndToys: es posible hacer esto con RxJava usando el segundo parámetro de flatMap (lo que no se usa tan comúnmente), que

[…] Combina elementos del Observable de origen con el Observable activado por esos elementos de origen, emitiendo estas combinaciones.

Fuente: documentación de RxJava

Deje que el código hable por sí mismo:

 observable catWithToysObservable =
    getCatObservable ()
        .flatMap ((cat) -> getToysForCatObservable (cat),
            (gato, juguetes) -> nuevos CatWithToys (gato, juguetes));

Vemos que este primer parámetro en flatMap toma Cat como parámetro y devuelve Toys. Luego, el segundo parámetro toma Cat and Toys (el resultado de la primera función) y devuelve el objeto CatWithToys. De esta manera, puede combinar muchas solicitudes dependientes a la API sin utilizar operadores flatMap anidados.

# 4 Solicitar paginación

Si desea paginar a través de algunos objetos desde la API, puede hacerlo fácilmente con RxJava. El truco consiste en fusionar todas las páginas hasta lograr un punto final (por ejemplo, la última solicitud le da resultados vacíos, o el recuento de elementos será correcto y correcto). Veamos el código:

Public Observable > getAllUsers () {
    return getUsersObservable (nulo);
}
Private Observable > getUsersObservable (Cadena final
    lastUserId) {
    volver apiAdapter
        .getData (lastUserId)
        .filter (userList ->! isLastPage (userList))
        .flatMap (this :: getNextPageUsersObservable);
}
Private Observable > getNextPageUsersObservable (final
    Lista  userList) {
    
    Observable > usersPageObservable =
        Observable.just (userList);
    int lastUserId = getLastUserId (userList);
    Observable > nextUsersPageObservable =
        getUsersObservable (lastUserId);
    return Observable.merge (nextUsersPageObservable,
        usersPageObservable);
}
isLastPage booleano privado (Lista final  userList) {
    return userList.isEmpty ();
}

En primer lugar, estamos solicitando una sola página sin ningún parámetro (o puede poner 0 aquí, dependiendo de su API), luego verificamos nuestra condición de lista final: si no llegamos al final, estamos solicitando algunos nuevas páginas con el parámetro de la última solicitud (podría ser la última identificación del usuario, o una fecha de la foto más nueva, o cualquier otra cosa) y la fusionaremos con el Observable anterior. Si llegamos al final de la lista, terminamos.

# 5 RxBus ligero

Si está utilizando un bus de eventos en su proyecto (no importa si se trata de Otto, Event Bus de Greenrobot u otra cosa), puede estar interesado en implementar su propio bus de eventos: ¡RxBus! Puede que se pregunte por qué estamos reinventando la rueda, en lugar de usar algo que fue hecho por otra persona.

Bueno, cuando vea lo fácil que es implementar su propio EventBus con RxJava, puede repensar poner esto como una biblioteca interna. Usted es independiente de los cambios en la biblioteca externa, por lo que puede ajustar RxBus para satisfacer sus necesidades y, si ya tiene RxJava en el proyecto, ¿por qué no lo usa para algo más?

clase pública RxBus {
    instancia privada estática final de RxBus = new RxBus ();
    Asunto final privado  rxBus;
    public RxBus () {
        PublishSubject  rxEventPublishSubject =
            PublishSubject.create ();
        rxBus = rxEventPublishSubject.toSerialized ();
    }
    public static RxBus getInstance () {
        instancia de retorno;
    }
    público Observable  getRxBus () {
        volver rxBus;
    }
    Publicación vacía pública (RxEvent rxEvent final) {
        rxBus.onNext (rxEvent);
    }
    clase pública RxEvent {}
}

El "núcleo" principal de RxBus es SerializedSubject (muy similar a PublishSubject, que utilizamos para detectar clics dobles, pero este es seguro para subprocesos). Simplemente creamos una clase singleton que contiene una referencia a este SerializedSubject. Si enviamos algún evento, emitimos elementos con SerializedSubject, si nos suscribimos al evento, nos suscribimos a recibir eventos de SerializedSubject. Simple, ¿no es así? Usamos el método toSerialized () porque queremos usar nuestro RxBus de diferentes hilos.

Conclusión

Como puede ver, hay muchas cosas que puede hacer con RxJava. Es útil para las vistas, la solicitud de datos y la comunicación interna en su aplicación. Recuerde, hay muchas soluciones para los problemas que presenté y RxJava puede no ser siempre la mejor, pero espero que estos consejos lo hayan inspirado a buscar otras soluciones para sus problemas.

¡Eso es! Espero que les gusten mis consejos. ¡Mantente sintonizado para más!