Como entender as quatro construções de uma rotina RxJava

Ayusch Jain Blocked Unblock Seguir Seguindo 9 de janeiro

Este artigo foi originalmente publicado aqui .

RxJava se tornou a arma mais importante no arsenal de desenvolvimento do Android. Todo desenvolvedor em 2019 deve começar a usá-lo em seus aplicativos, se ainda não o tiverem feito. De acordo com a definição oficial do RxJava:

“O RxJava é uma implementação Java VM de Extensões Reativas : uma biblioteca para composição de programas assíncronos e baseados em eventos usando sequências observáveis.”

Essa definição pode soar intimidante com todos os termos técnicos, como Java VM, Extensões Reativas, sequências assíncronas baseadas em eventos, observáveis, etc. Mas, adivinhe? Você tem usado todas essas coisas no seu dia-a-dia tarefas de desenvolvimento android sem saber.

Nota: Eu estou supondo que se você está procurando mergulhar fundo no RxJava, então você tem um bom conhecimento da linguagem de programação Java. Se não, você pode encontrar várias escolas on-line que podem ajudá-lo com isso.

Começando

Vamos começar com o Java VM (ou JVM). Já se perguntou como o seu código escrito usando o alfabeto Inglês é traduzido para pixels na tela? Como sua cor muda no código se traduz em mudanças de cor na tela? Bem, tudo é feito pela JVM.

Primeiro, seu código-fonte é compilado em Bytecode pelo compilador. Agora vem a JVM que pega o Bytecode e o converte em algo que a máquina pode entender. Em outras linguagens , o compilador converte o código para um sistema específico, mas o compilador do Java converte o código-fonte em Bytecode, que pode ser executado em qualquer máquina com JVM.

Agora, você entende porque o Kotlin pode ser usado para escrever aplicativos Android? Se não, então fique atento ao meu próximo post.

Extensões reativas

Extensões reativas ou ReactiveX já existe há muito tempo. Não é nada além de uma API que facilita a programação reativa.

Inconscientemente, temos escrito código reativo o tempo todo. Por exemplo, quando ocorre um clique de botão, ele aciona um determinado bloco de código no seu arquivo de origem. Esta é uma programação reativa! Um pedaço de código reagiu a um evento (clique no botão neste caso).

O Reactive Extensions não é específico de nenhuma linguagem de programação, mas sim de uma metodologia que foi implementada em linguagens como Java (RxJava), JavaScript (RxJS), C # (Rx.NET), Scala (RxScala) e muitas outras! Então, você vê, o ReactiveX não é específico do idioma, mas é mais um padrão de design que pode ser implementado em qualquer idioma.

Construções de RxJava

O RxJava tem basicamente 4 construções:

  • Observável
  • Agendador
  • Observador
  • Assinante

Esses 4 componentes estão presentes em todas as rotinas do RxJava. Embora não sejam necessários, recomendo que você se atenha a eles como iniciante. Quando estiver confortável com o RxJava, você pode jogar as regras pela janela e começar a brincar. Mas antes de chegar a esse nível, basta seguir o básico.

Então, vamos analisar cada uma dessas construções em mais detalhes.

Observável

Um Observable é exatamente o que parece: algo que pode ser observado. Um observável (botão) em RxJava é observado por um Observer (código que é executado em um clique de botão) que reage a qualquer evento emitido (evento de clique de botão) pelo observável. Esse padrão facilita as operações simultâneas, já que o encadeamento principal não precisa ser bloqueado enquanto aguarda que o observável emita eventos. O observador está sempre pronto para reagir assim que o observável emite.

RxJava segue o padrão observador no qual um Observer (explicado mais tarde) assina um Observable que emite eventos / dados e então reage de acordo. Os conceitos no RxJava são melhor explicados com a ajuda dos diagramas do Marble. Então aqui está uma para você:

Em ReactiveX, muitas instruções podem ser executadas em paralelo e seus resultados são posteriormente capturados, em ordem arbitrária, por “ observadores ”. Em vez de chamar um método, você define um mecanismo para recuperar e transformar os dados, na forma de um “ Observável. Então você assina um observador para ele, no ponto em que o mecanismo previamente definido dispara em ação com o observador em pé, sentinela para capturar e responder às suas emissões sempre que estiverem prontas.

Uma vantagem dessa abordagem é que, quando você tem um monte de tarefas que não dependem umas das outras, você pode iniciá-las todas ao mesmo tempo, em vez de esperar que cada uma termine antes de iniciar a próxima. Dessa forma, todo o seu pacote de tarefas leva apenas o tempo para ser concluído como a tarefa mais longa do pacote.

Agendadores (importante)

Um dos recursos super legais do RxJava é que ele oferece simultaneidade instantânea. Concorrência é realmente difícil de entender. Mesmo hoje, é um dos tópicos mais complexos em ciência da computação e é realmente difícil de implementar.

Os gênios que escreveram o RxJava abstraíram todas essas complexidades para nós, nos dando APIs relativamente mais simples para trabalhar. O RxJava manipula a simultaneidade com a ajuda dos Agendadores. Na rotina RxJava, temos um operador chamado

 subscribeOn () 

Basicamente diz: Aqui está um observável e um observador, pegue-os e estabeleça sua conexão neste tópico em particular.

Tudo isso pode ser conseguido com Java puro usando Threads, Manipuladores, Executores, etc, mas os Schedulers são apenas uma maneira elegante de lidar com isso.

Geralmente, a maioria das operações é delegada ao thread de IO. Mas existem muitos outros tipos de agendadores. Aqui estão alguns dos mais comumente usados:

  • Schedulers.io (): usado para tarefas não-computacionais de E / S, como Gerenciamento de Arquivos, fazer chamadas de rede, gerenciamento de banco de dados, etc. Esse conjunto de encadeamentos destina-se a ser usado para tarefas assíncronas.
  • Schedulers.computation (): Como o nome sugere, destina-se a ser usado para tarefas pesadas com computação, como processamento de imagem, processamento de conjunto de dados, etc. Ele tem tantos números de threads quanto o número de processadores disponíveis. Mas você deve ter cuidado ao usá-lo, pois pode levar à degradação no desempenho devido à troca de contexto nos threads.
  • Schedulers.from (Executor ex): cria e retorna um planejador personalizado respaldado por um executor específico.
  • Schedulers.mainThread (): Ei, eu não me esqueci de você Android Devs ? Isto é fornecido pela biblioteca RxAndroid e nos fornece o segmento principal. Tenha cuidado para não executar tarefas de execução longa neste encadeamento, pois ele é síncrono e pode levar a ANRs.

Há também um operador chamado

 observeOn () 

Como vimos acima, subscribeOn () instrui a fonte em qual Observável qual encadeamento irá emitir itens – este encadeamento irá empurrar as emissões até o nosso Observador. No entanto, se encontrar um observOn () em qualquer lugar da cadeia, ele alternará e transmitirá as emissões usando esse Agendador para as operações restantes (downstream).

Observador / Assinante

Como um artista precisa de uma audiência, o observável também precisa de alguém para observá-lo enquanto ele emite itens. Pode haver emissões sem um observador (google hot and cold observables), mas isso é uma história para outro momento.

Um observador se inscreve no observável com a ajuda do método subscribe (). Assim que o observador se inscreve, está pronto para receber notificações do observável.

Ele fornece três métodos para manipular as notificações:

  • onNext (): neste método, a notificação é entregue ao assinante sem erros.
  • onError (): Um throwable é enviado ao assinante em onError, delineando o erro.
  • onComplete (): Isso é chamado no final quando a fonte termina de emitir.

Dependendo se você estava observando no thread principal ou em um thread separado, você estará recebendo as emissões no onNext no thread principal ou em um novo thread.

Quando um Assinante se inscreve em um Publicador, em seguida, no RxJava2, uma instância Descartável é retornada, que pode ser usada para cancelar / descartar um Assinante externamente via Disposable :: dispose ().

Aqui está um diagrama para ajudá-lo a entender melhor esse relacionamento:

[id de legenda = ”anexo_1032" alinhar = "aligncenter" largura = "1340"]

Fonte da imagem [ Mindorks ] [/ caption]

Devo usar o RxJava?

Em vez de fazer meu caso verbalmente, deixarei que você decida. Basta percorrer o código abaixo.

Java

 Listar <Inteiro> temp = Arrays.asList (5,8,9,20,30,40); 
Listar <Integer> javaList = new ArrayList <> ();
 para (Integer i: temp) { 
se (i> 10)
javaList.add (i);
}

RxJava

 Lista <Integer> rxlist = Stream.of (5, 8, 9, 20, 30, 40) .filter (x -> x> 10). 
collect (Collectors.toList ());

Java

 TPExecutor.execute (() -> api.getUserDetails (userId)) 
.runOnUIAfterBoth (TPExecutor.execute (() -> api.getUserPhoto (userId)), p -> {
// Faça sua tarefa
});

RxJava

 Observable.zip (api.getUserDetails2 (userId), api.getUserPhoto2 (userId), (detalhes, foto) -> Pair.of (detalhes, foto)) 
.subscribe (p -> {
// Faça sua tarefa.
});

AsyncTask

 classe privada MyTask estende AsyncTask <String, Integer, Boolean> 
{
@Sobrepor
protegido Boolean doInBackground (String ... caminhos)
{
para (int index = 0; index <paths.length; index ++)
{
resultado booleano = copyFileToExternal (caminhos [index]);
 if (resultado == verdadeiro) 
{
// atualiza a interface do usuário
publishProgress (índice);
}
outro
{
// pare o processo em segundo plano
retorna falso;
}
}
 retorno verdadeiro; 
}
 @Sobrepor 
protected void onProgressUpdate (Integer ... valores)
{
super.onProgressUpdate (valores);
int count = valores [0];
// isso atualizará meu textview para mostrar o número de arquivos copiados
myTextView.setText ("Total de arquivos:" + count);
}
 @Sobrepor 
protected void onPostExecute (resultado booleano)
{
super.onPostExecute (resultado);
if (resultado)
{
// exibe um diálogo de sucesso
ShowSuccessAlertDialog ();
}
outro
{
// exibe um diálogo de falha
ShowFailAlertDialog ();
}
}
}

RxJava

 Observable.fromArray (getPaths ()) 
.map (caminho -> copyFileToExternal (caminho))
.subscribeOn (Schedulers.io ())
.observeOn (AndroidSchedulers.mainThread ())
.subscribe (aInteger -> Log.i ("teste", "atualização da interface do usuário"),
throwable -> ShowFailAlertDialog),
() -> ShowSuccessAlertDialog ());

Você pode ver que o código RxJava é muito mais legível e conciso (expressões lambda podem ser um pouco assustadoras se você não estiver familiarizado com elas, mas uma vez que você começar a usá-las, este código pareceria uma segunda natureza para você). E há muitos outros exemplos em que os operadores do RxJava liberam seu poder sobre a programação Java tradicional.

Desvantagens

Eu não encontrei nenhuma desvantagem em usar o RxJava até este ponto – apenas que ele tem uma curva de aprendizado realmente íngreme . Se você ainda não está familiarizado com o padrão Observer, o Java 8 (não obrigatório mas realmente útil), o lambdas etc, você encontrará o código RxJava realmente intimidador.

Mas quando você começar a aplicar o seu código no RxJava, você vai lentamente começar a pegar o jeito e vai perceber que a maioria das construções no RxJava permanecem as mesmas.

Este post tem uma lista completa de recursos para você começar.