RxJava and Kotlin #1

Bruno Hensel
Android Dev BR
6 min readFeb 11, 2021

--

Entendendo o que é RxJava e como criar Observables

Este é o primeiro post de uma série de post que farei abordando o framework RxJava e nele vamos aprender oque é o RxJava, oque é um observable, como ler um marble graph, como criar e se subscrever à um observable e tipos diferentes de observables.

O objetivo desta série é abordar, gradualmente, os vários aspectos e APIs do RxJava, bem como explicar os conceitos do Rx e mostrar como utilizar suas várias APIs.

O que é RxJava?

RxJava é uma biblioteca utilizada para compor códigos baseados em eventos asincronos, utilzando para tanto o observable pattern e vários operadores. Isso possibilita o código reagir à novos eventos e processá-los em uma forma funcional e isolada. Ou seja, utilizando essa biblioteca você conseguirá observar uma sequência de eventos asincronos em seu app e responder a cada evento da maneira desejada.

Importante saber que os três pilares do RxJava são: Observables, Operators e Schedulers. Neste artigo iniciaremos a abordagem sobre Observables.

Pera aí, vai com calma. Programação asincrona?

Você pode pensar em programação asincrona como operações que ocorrem simulteneamente, mas que não bloqueiam as execuções umas das outras. Por exemplo, você exibe um progress bar em sua UI enquanto faz uma chamada para obter dados de uma API.

Observables

A classe Observable<T> é a base do RxJava ao possibilitar a criação asincrona de sequência de eventos que podem “carregar” uma representação imutável de seu elemento T. Aqui “T” nada mais é do que uma menção de um tipo generico de data, pode ser um Int ou uma String ou uma lista de objetos, etc.

Mas afinal, o que é um Observable?

Você poderá encontrar por aí referencias tais como “observables”, “observable sequence”, “stream” e “chain”, que são usados de forma intercalada no mundo do Rx, e na boa, tudo quer dizer a mesma coisa: sequência de eventos asincronos.

Observables produzem uma sequência de eventos, cujo processamento é denominado de emitting, durante um período de tempo. Esses eventos contém elementos, como já mencionado acima, tais como números. Podemos demonstrar o conceito aqui abordando utilizando marble diagrams:

A seta que vai da esquerda para a direita representa a linha do tempo do observable, os números dentro de cada circulos representam elementos de uma sequência. O elemento 1 foi emitido(para tanto o método onNext é chamado), algum tempo depois o elemento 2 foi emitido e por aí vai, até que o observable termine suas operações e chame o método onComplete, o que faz com que ele não emita mais nenhum elemento, isso é representado pelo traço vertical à direita. Caso ocorra algum erro durante o processo o método onError é chamado e a stream é terminada, esse erro é representado por um “X” na linha do tempo.

Agora que você já pegou um pouco sobre o que é um observable, vamos botar a mão na massa e criar alguns para vê-los em ação.

Subscrevendo ao observable

Antes de iniciarmos a criação de um observable, é importante aprendermos como fazer a subscrição de um observable. Nesse ponto, importante relembrar que um observable nada mais é que um sequência, e esta sequência não será emitida até que haja um subscritor (subscriber).

Podemos fazer uma analogia com um BroadcastReceiver(), onde você precisa chamar registerReceiver() para registrar e receber os eventos, mas que, para o nosso observable, você chama subscribe() .

Podemos ir além e exemplificar a subscrição à um observable como chamar o next() em um Interator do Kotlin:

Veremos o subscribing em ação abaixo.

Criando observables

No mundo Rx, os métodos que atuam sobre os observables são chamados de operadores (operators). Para criação de observables, podemos contar com os seguintes operadores: just, fromInterable, empty, never, range e create.

Just:

O operador just, como o nome indica, cria uma sequência contendo apenas os elementos que você passou.

Observable de inteiros:

Observable de uma lista:

FromIterable:

Este operador irá criar um observable de cada item de uma lista. Ele retira todos os elementos da lista, e emite cada um deles. O resultado é o mesmo que o just(). Ou seja, você recebe uma lista, mas aos invés de emitr a lista, você quer emitir cada elemento da lista.

Empty:

Até agora aprendemos como criar observables com 1 item ou com vários, mas e se quisermos criar um observable com zero elementos? Para isso existe o opertador empty, que, diferentemente dos outros observables, emite apenas complete.

Este operador pode ser útil se você precisar retornar um observable que, encerra sua stream imediatamente ou que tenha zero elementos.

Never:

Em contra partida ao empty, o operador never cria um observable que não emite nada e que também nunca encerra a stream. No exemplo abaixo nada é printado no console.

Range:

Como aprendemos até aqui, é possível criar observables com zero, um ou vários elementos, mas também é podemos criar um observable a partir de um range de elementos.

Create:

Nos exemplos anteriores vimos a criação de observables que já contemplam o método onNext() , sem a necessidade de você ter que invocar tal método para a emissão de algum elemento. Contudo, é possível utilizar o operador create para criar um observable do zero! O operador create pode ser útil para criar um observable que age como ponte entre o mundo reactivo e o mundo dos callbacks.

Este operador leva um único parâmetro do tipo ObservableOnSubscribe<T> chamado source, que nada mais é do que uma interface que expõe o método subscribe() . Este método requer um Emitter<T> que possui alguns métodos que serão necessários na hora de montar o seu observable, a saber, onNext, onComplete e onError. A teoria por traz deste operator por ser meio complicada, mas sua utilização não é.

Podemos sintezizar a sequência da seguinte forma:

  • 1- A String First value é emitida através do método onNext
  • 2- Um evento complete é emitido através do método onComplete
  • 3- Uma nova String Second value é emitda através do método onNext

Você está absolutamente correto ao supor que a segunda String não foi printada no console pelo fato de que nosso observable terminou suas obrigações após o método onComplete ser envocado, e por conta disso, nenhuma emissão mais é enviada stream abaixo. O mesmo raciocínio é válido se o método onError foi invocado, qualquer tentativa de emissão via onNext depois do erro não será recebida por quem estiver observando nossa chain de eventos.

Outros tipos de observables:

Além do observable que vimos até aqui, existem outros tipos especializados de observables que você pode utilizar. São eles: Single, Maybe e Completable.

  • Singles irá emitir apenas sucesso (passando seu objeto stream abaixo) ou um evento de erro. O sucesso, na verdade, é composto pelo onNext e onComplete. Esse tipo de observable é bem útil quando se trata de eventos únicos, onde você não precisa manter a stream aberta para observar novos eventos. Ex. Fazer uma chamada de HTTP para obtenção de alguma data.
  • Completable irá emitir apenas um evento completed ou erro. Com este tipo de observable você não liga para a data, e sim somente para o evento.
  • Maybe é a junção dos dois acima, ele emite ou um evento de sucesso ou de erro, ou completed, mas, ao contrário do Single, ele pode carregar um valor com o evento sucesso pela stream, ou nenhum valor. É exatamente isso que o operador firstElement() faz, ou ele emite apenas o primeiro item já emitido pelo nosso observable, ou completa a operação se o observable for vazio.

TL;DR

Nesse epsódio aprendemos que no mundo Rx tudo é uma sequência de eventos; observables apenas começam a emitir algo quando eles são subscritos; há vários operadores destinaos à criação de um observable, cada um para uma situação diferente, e, por fim, que o operador create é destinado quando você quiser controlar a emissão dos elementos pela stream.

Vimos também que há alguns tipos especiais de observables, quando você precisar de uma abordagem diferente.

É isso! No próximo post veremos como usar o dispose para cancelar uma subscrição e prevenir memory leaks, bem como abordaremos o conceito de Subjects.

--

--