Os operadores são usados para resolver o problema de transformar objetos observáveis. Os operadores são usados para modificar os eventos emitidos pelo observável entre observável e o assinante final. O RXJava fornece muitos operadores úteis.
Por exemplo, o operador do mapa é usado para converter um evento em outro.
Obsertable.Just ("Olá, mundo!") .Map (novo func1 <String, String> () {@Override public String Call (String S) {return s + "-dan";}}) .subScribe (s -> System.out.println (s)); Usar lambda pode ser simplificado para
Obsertable.Usjust ("Olá, mundo!") .Map (S -> S + "-dan") .SubScribe (S -> System.out.println (S));Não é legal? O operador map () é usado para transformar o objeto observável. O operador do mapa retorna um objeto observável, para que uma chamada de cadeia possa ser implementada e o operador do mapa é usado várias vezes em um objeto observável e, finalmente, os dados mais simples são passados para o objeto assinante.
Operador de mapa Avançado
O mais interessante do operador do mapa é que ele não precisa devolver o tipo retornado pelo objeto observável. Você pode usar o operador do mapa para retornar um objeto observável que emite o novo tipo de dados.
Por exemplo, no exemplo acima, o assinante não se importa com a sequência retornada, mas deseja o valor de hash da string.
Obsertable.Just ("Olá, mundo!") .Map (novo func1 <String, Integer> () {@Override public Integer Call (String s) {return s.hashcode ();}}) .Subscribe (i -> System.out.println (integger.tostring (i)); Muito interessante, certo? Nosso observável inicial retorna uma string, enquanto o assinante final recebe um número inteiro. Obviamente, o uso do Lambda pode simplificar ainda mais o código:
Obsertable.Just ("Olá, mundo!") .MAP (S -> s.HashCode ()) .SubScribe (i -> System.out.println (Integer.toString (i))); Como mencionado anteriormente, quanto menos coisas se inscrevem, melhor. Vamos adicionar outro operador de mapa.
Obsertable.UsT ("Olá, mundo!") .Map (S -> s.HashCode ()) .Map (i -> Integer.ToString (i)) .Subscribe (S -> System.out.println (S)); Não está convencido?
Você acha que nosso exemplo é muito simples para convencê -lo? Você precisa entender os dois pontos a seguir:
1. Observável e assinante podem fazer qualquer coisa
Observável pode ser uma consulta de banco de dados, e o assinante é usado para exibir resultados de consulta; Observável pode ser um evento de clique na tela e o assinante é usado para responder para clicar em eventos; Observável pode ser uma solicitação de rede e o assinante é usado para exibir os resultados da solicitação.
2. Observáveis e assinantes são independentes do processo de transformação intermediária.
Qualquer número de mapas pode ser adicionado ou diminuído entre observável e assinante. Todo o sistema é altamente combinável e os dados operacionais são um processo muito simples.
Exemplo
1. Preparação
Suponha que eu tenha um método como este:
Este método retorna a lista de URL de um site com base na sequência de entrada (AHHA, mecanismo de pesquisa)
Observável <list <string>> consulta (texto da string);
Agora, quero criar um sistema robusto que possa consultar strings e exibir os resultados. Com base no conteúdo do blog anterior, podemos escrever o seguinte código:
Query ("Olá, mundo!") .Subscribe (URLs -> {for (String url: urls) {System.out.println (url);}});Obviamente, esse tipo de código não pode ser tolerado, porque o código acima nos levou a perder a capacidade de alterar o fluxo de dados. Uma vez que queremos alterar cada URL, só podemos fazê -lo no assinante. Não usamos um operador de mapa () tão legal! ! !
Obviamente, posso usar o operador do mapa. A entrada do mapa é a lista de URLs. Ao processar, ele ainda precisa atravessar cada um, o que também é muito doloroso.
Felizmente, há também o método observável.From (), que recebe uma coleção como entrada e depois produz um elemento para o assinante por vez:
Obsertable.From ("url1", "url2", "url3") .Subscribe (url -> system.out.println (url)); Vamos usar esse método na cena agora:
Query ("Olá, mundo!") .Subscribe (URLs -> {observable.From (URLs) .Subscribe (url -> System.out.println (url));});
Embora o loop para cada loop seja removido, o código ainda parece confuso. Várias assinaturas aninhadas não apenas parecem feias e difíceis de modificar, mas, mais seriamente, isso destruirá alguns dos recursos do rxjava que ainda não mencionamos.
2. Melhoria
O Salvador está aqui, ele é Flatmap ().
Obsertable.flatmap () recebe a saída de um observável como entrada e produz outro observável ao mesmo tempo. Olhe diretamente para o código:
Query ("Hello, World!") .FlatMap (novo Func1 <List <String>, observável <string>> () {@Override public observável <string> Call (list <string> urls) {return observable.from (urls);}}). Aqui eu publiquei todo o código da função para facilitar você para entender o que está acontecendo. Usar Lambda pode simplificar bastante o comprimento do código:
Query ("Olá, mundo!") .FlatMap (URLs -> obsertable.From (URLS)) .Subscribe (url -> System.out.println (URL));Flatmap () parece estranho? Por que ele retorna outro observável? O ponto principal da compreensão do FlatMap é que a nova saída observável do Flatmap é exatamente o que queremos receber no assinante. Agora, o assinante não recebe mais a lista <String>, mas recebe algumas seqüências únicas de colunas, assim como a saída do observável.From ().
Esta parte também é a parte mais difícil quando aprendi Rxjava pela primeira vez. Uma vez que eu percebi de repente, muitas das perguntas em Rxjava foram resolvidas.
3. Pode ser melhor
flatmap () não é realmente uma idéia melhor, pode retornar qualquer objeto observável que deseje retornar.
Por exemplo, o seguinte método:
// Retorna o título do site e, se for 404, retorne a observar NULL <String> getTitle (String URL);
Seguindo o exemplo anterior, agora não quero mais imprimir o URL, mas imprimir o título de cada site que recebo. O problema é que meu método só pode passar em um URL por vez, e o valor de retorno não é uma string, mas um objeto Observabl que gera uma string. O uso do Flatmap () pode simplesmente resolver esse problema.
Query ("Olá, mundo!") .FlatMap (URLS -> obsertable.From (URLS)) .FlatMap (novo Func1 <String, observável <string>> () {@Override public observable <String> Call (String url) {return gettitle (url);}} () .subsscribe ( -systems); 4. Use Lambda:
Query ("Olá, mundo!") .FlatMap (URLs -> obsertable.From (URLS)) .flatmap (url -> gettitle (url)) .subscribe (título -> System.out.println (title)); Não se sente incrível? Na verdade, posso combinar vários métodos independentes para retornar objetos observáveis! Muito bonito!
Mais do que isso, também combinei as chamadas de duas APIs em uma chamada acorrentada. Podemos vincular o maior número possível de chamadas de API. Todos devem saber como é doloroso sincronizar todas as chamadas da API e, em seguida, combinar os resultados do retorno de chamada de todas as chamadas de API nos dados a serem exibidos. Aqui, evitamos com sucesso o inferno de retorno de chamada (retornos de chamada aninhados de várias camadas, dificultando a leitura do código). Agora toda a lógica está envolvida nessa chamada simples e responsiva.
5. Até agora, operadores ricos <r />, entramos em contato com dois operadores e há mais operadores no RXJava, então como usamos outros operadores para melhorar nosso código?
gettitle () retorna nulo se o URL não existir. Não queremos produzir "nulo", então podemos filtrar o valor nulo da lista de títulos retornados!
Query ("Olá, mundo!") .FlatMap (URLs -> obsertable.From (URLS)) .flatmap (url -> gettitle (url)) .filter (title -> title! = null) .subscribe (título -> system.out.println (title));O filtro () produz os mesmos elementos que a entrada e filtra aqueles que não atendem aos critérios de verificação.
Se queremos apenas até 5 resultados:
Query ("Olá, mundo!") .FlatMap (URLS -> obsertable.From (URLS)) .FlatMap (url -> gettitle (url)) .Filter (title -> title! = null).Take () produz o número máximo de resultados.
Se queremos salvar cada título no disco antes de imprimir:
Query ("Olá, mundo!") .FlatMap (URLS -> obsertable.From (URLS)) .FlatMap (url -> gettitle (url)) .Filter (title -> title! = null).Doonnext () nos permite fazer algumas coisas extras antes de gerar um elemento de cada vez, como salvar o título aqui.
É fácil ver como é fácil operar o fluxo de dados aqui? Você pode adicionar quantas operações quiser e não estragar seu código.
O rxjava contém um grande número de operadores. O número de operadores é um pouco assustador, mas vale a pena conferir um a um para que você possa saber quais operadores podem ser usados. Pode levar algum tempo para entender esses operadores, mas depois de entender, você entenderá completamente o poder do RXJava.
Você pode até escrever operadores personalizados! Este blog não pretende personalizar o operador. Se você quiser, por favor, pesquise no Google.
Como você está se sentindo?
Bem, você é cético e é difícil de convencer, então por que você se importa com esses operadores?
Porque os operadores permitem que você faça qualquer coisa com o fluxo de dados.
Vincular uma série de operadores pode realizar uma lógica complexa. O código é dividido em uma série de trechos que podem ser combinados. Este é o charme da programação da função reativa. Quanto mais você o usa, mais você mudará seu pensamento de programação.
Além disso, o rxjava também facilita o processamento de dados. No último exemplo, chamamos duas APIs, processamos os dados retornados pela API e o salvamos no disco. Mas nosso assinante não sabe disso, apenas acha que está recebendo um objeto <String> observável. Boa embalagem também traz conveniência de codificação!
Na terceira parte, apresentarei alguns outros recursos interessantes do RXJava, como manuseio de erros e simultaneidade, que não são usados diretamente para processar dados.