Quando usar o RxJava no Android e quando usar o LiveData dos componentes arquitetônicos do Android?


186

Não estou entendendo o motivo de usar o RxJava no Android e o LiveData a partir dos componentes arquitetônicos do Android. Seria realmente útil se os casos de uso e as diferenças entre os dois forem explicados juntamente com um exemplo de exemplo na forma de código que explica as diferenças entre os dois.


6
Você já encontrou um bom motivo? Eu estou querendo saber o mesmo ...
IgorGanapolsky 16/18

Respostas:


117

O Android LiveData é uma variante do padrão original de observador, com a adição de transições ativas / inativas. Como tal, é muito restritivo em seu escopo.

Usando o exemplo descrito no Android LiveData , uma classe é criada para monitorar os dados de localização, registrar e cancelar o registro com base no estado do aplicativo.

O RxJava fornece operadores muito mais generalizados. Vamos supor que este observável forneça dados de localização:

Observable<LocationData> locationObservable;

A implementação do observável pode ser construída usando Observable.create() para mapear as operações de retorno de chamada. Quando o observável é inscrito, o retorno de chamada é registrado e, quando é cancelado, o retorno de chamada não é registrado. A implementação é muito semelhante ao código fornecido no exemplo.

Vamos supor também que você tenha um observável que emita true quando o aplicativo está ativo:

Observable<Boolean> isActive;

Em seguida, você pode fornecer todas as funcionalidades do LiveData da seguinte maneira

Observable<LocationData> liveLocation =
  isActive
    .switchMap( active -> active ? locationObservable : Observable.never() );

O switchMap()operador fornecerá o local atual como um fluxo ou nada se o aplicativo não estiver ativo. Depois de ter o liveLocationobservável, você pode fazer muitas coisas usando os operadores RxJava. Meu exemplo favorito é:

liveLocation.distinctUntilChanged()
  .filter( location -> isLocationInAreaOfInterest( location ) )
  .subscribe( location -> doSomethingWithNewLocation( location ) );

Isso só executará a ação quando o local for alterado e o local for interessante. Você pode criar operações semelhantes que combinam operadores de tempo para determinar a velocidade. Mais importante, você pode fornecer controle detalhado sobre se as operações ocorrem no encadeamento principal ou em um encadeamento em segundo plano ou em vários encadeamentos, usando operadores RxJava.

O objetivo do RxJava é que ele combina controle e tempo em um único universo, usando operações fornecidas pela biblioteca ou mesmo operações personalizadas que você fornece.

O LiveData trata apenas de uma pequena parte desse universo, o equivalente à construção do liveLocation.


2
Obrigado, os documentos do LiveData não parecem mais fazer referência a um exemplo de local. Existem pontos mais interessantes (com uma amostra de localização) aqui: androidkt.com/livedata
Daniel Wilson

5
@DanielWilson o link não está mais disponível.
Tura #

Cara eu não me lembro wtf estava naquele link: DI como código de exemplo de Mark Allison por dados ao vivo: blog.stylingandroid.com/architecture-components-livedata
Daniel Wilson

3
The point of RxJava is that it combines control and timing into a single universe, using operations provided from the library, or even custom operations that you provide. Mas o ciclo de vida do LiveData não está ciente. Se usássemos o Rx, não precisaríamos lidar com as mudanças no ciclo de vida?
Sparker0i

@ Sparker0i tem razão aqui. O RxJava não reconhece o ciclo de vida. nós temos que lidar manualmente. onde, como no LiveData, ele já cuida do ciclo de vida.
Aks4125

119

Em relação à pergunta original, RxJava e LiveData se complementam muito bem.

LiveDatabrilha na camada ViewModel, com sua forte integração com os ciclos de vida do Android e ViewModel. RxJavafornece mais recursos em transformações (como mencionado por @Bob Dalgleish).

Atualmente, estamos usando as RxJavacamadas de fonte de dados e repositório, e ele é transformado em LiveData(usando LiveDataReactiveStreams) no ViewModels (antes de expor os dados a atividades / fragmentos) - bastante satisfeito com essa abordagem.


8
Se o entendemos corretamente, o LiveData é útil apenas para implementações específicas da interface do Android. Se estamos apenas construindo um aplicativo genérico com Arquitetura Limpa e compartilhando essa arquitetura com outras plataformas, o RxJava é mais adequado que o LiveData?
IgorGanapolsky

@IgorGanapolsky que linguagem / estruturas você usa para aplicativos genéricos?
Kzotin

APIs independentes do Android e Clean Arch escritas em Java / Kotlin.
IgorGanapolsky

1
você pode sugerir algum exemplo de LiveDataReactiveStreams na sua resposta?
Pawan

2
@kzotin você não precisa disso observeOn, LiveDataReactiveStreamsfaz assim mesmo ligando LiveData.postValue(). E não há garantia de que você subscribeOnterá qualquer efeito em geral.
precisa saber é o seguinte

77

Há muitas diferenças entre o LiveData e o RxJava:

  1. LiveData não é um STREAM, enquanto no RxJava tudo (literalmente tudo) é um STREAM .
  2. LiveData é uma classe de portador de dados observável. Ao contrário de um observável regular, o LiveData reconhece o ciclo de vida, o que significa que respeita o ciclo de vida de outros componentes do aplicativo, como atividades, fragmentos ou serviços. Essa conscientização garante que o LiveData atualize apenas observadores de componentes de aplicativos que estão em um estado de ciclo de vida ativo.
  3. O LiveData é síncrono , portanto, você não pode executar um pedaço de código (chamada de rede, manipulação de banco de dados etc.) de forma assíncrona usando apenas o LiveData como você faz com o RxJava.
  4. O melhor que você pode fazer para explorar ao máximo essa dupla é usar o RxJava para sua lógica de negócios (chamada de rede, manipulação de dados etc., qualquer coisa que ocorra dentro e fora do Repositório ) e usar o LiveData para sua camada de apresentação. Com isso, você obtém recursos de transformação e fluxo para sua lógica de negócios e operação com reconhecimento do ciclo de vida para sua interface do usuário.
  5. LiveData e RxJava se complementam se usados ​​juntos. O que quero dizer é: faça tudo com o RxJava e, no final, quando você quiser atualizar a interface do usuário, faça algo como o código fornecido abaixo para mudar seu Observable para LiveData. Portanto, sua View (UI) observa o LiveData no ViewModel, onde o LiveData não passa de MutableLiveData não mutável (ou MutableLiveData é LiveData mutável).
  6. Portanto, a questão aqui é: por que você deveria usar o LiveData em primeiro lugar? Como você pode ver abaixo no código, você armazena sua resposta do RxJava para MutableLiveData (ou LiveData) e seu LiveData reconhece o ciclo de vida, portanto, de certa forma, seus dados reconhecem o ciclo de vida. Agora, imagine a possibilidade de seus dados saberem quando e quando não atualizar a interface do usuário.
  7. LiveData não possui um histórico (apenas o estado atual). Portanto, você não deve usar o LiveData para um aplicativo de bate-papo.
  8. Quando você usa o LiveData com o RxJava, não precisa de itens como MediatorLiveData , SwitchMap , etc. Eles são ferramentas de controle de fluxo e o RxJava é melhor nisso muitas vezes.
  9. Veja o LiveData como um detentor de dados e nada mais. Também podemos dizer que o LiveData é um consumidor que reconhece o ciclo de vida.

    public class RegistrationViewModel extends ViewModel {
        Disposable disposable;

        private RegistrationRepo registrationRepo;
        private MutableLiveData<RegistrationResponse> modelMutableLiveData =
                new MutableLiveData<>();

        public RegistrationViewModel() {
        }

        public RegistrationViewModel(RegistrationRepo registrationRepo) {
            this.registrationRepo = registrationRepo;
        }

        public void init(RegistrationModel registrationModel) {
            disposable = registrationRepo.loginForUser(registrationModel)
                    .subscribeOn(Schedulers.io())
                    .observeOn(AndroidSchedulers.mainThread())
                    .subscribe(new Consumer<Response<RegistrationResponse>>() {
                        @Override
                        public void accept(Response<RegistrationResponse>
                                                   registrationModelResponse) throws Exception {

                            modelMutableLiveData.setValue(registrationModelResponse.body());
                        }
                    });
        }

        public LiveData<RegistrationResponse> getModelLiveData() {
            return modelMutableLiveData;
        }

       @Override
       protected void onCleared() {
                super.onCleared();
            disposable.dispose();
         }
    }

5
Veja o LiveData como um detentor de dados e nada mais. ==> SIM
Lou Morda

3
Belo exemplo. Você esqueceu de declarar o descartável e seria bom limpá-los onCleared.
Snicolas

Você poderia, por favor, explicar como o viverata é síncrono? Tanto quanto sei, podemos enviar o objeto Livedata para outro segmento e, em seguida, esse segmento pode pós-valor que o observador pode ouvir no MainThread.
Hitesh Bisht

Se você ler novamente o que eu escrevi isso significa que você não pode trabalhar em outro segmento apenas (sim, eu usei "apenas" mesmo lá), utilizando LiveData como você pode fazer usando RxJava
Abhishek Kumar

O ciclo de vida não é um grande diferencial para o LiveData? Você 1. descreve o que seu pipeline precisa fazer e quais são seus resultados finais, 2. assina o resultado nas cláusulas "observe" e 3. o pipeline está sendo operado apenas se o seu estado de ciclo de vida permitir.
Srg 21/08/19

29

Na verdade, LiveData não é uma ferramenta essencialmente diferente RxJava, então por que foi introduzido como um componente de arquitetura, quando RxJavapoderia facilmente ter gerido o ciclo de vida, armazenando todas as assinaturas de observáveis em um CompositeDispoable objeto e, em seguida, descartá-los em onDestroy() do Activity ou onDestroyView() da Fragment usando apenas um linha de código?

Respondi a essa pergunta completamente criando um aplicativo de pesquisa de filmes uma vez usando o RxJava e depois o LiveData aqui .

Mas, resumindo, sim, poderia, mas isso precisaria substituir os métodos relevantes do ciclo de vida, além de ter o conhecimento básico do ciclo de vida. Isso ainda pode não fazer sentido para alguns, mas o fato é que, de acordo com uma das sessões do Jetpack no Google I / O 2018, muitos desenvolvedores acham o gerenciamento do ciclo de vida complexo. Os erros de travamento decorrentes da não manipulação da dependência do ciclo de vida podem ser outro sinal de que alguns desenvolvedores, mesmo que tenham conhecimento do ciclo de vida, esquecem de cuidar disso em todas as atividades / fragmentos usados ​​no aplicativo. Em aplicativos grandes, isso pode se tornar um problema, apesar do efeito negativo que isso pode ter na produtividade.

A conclusão é que, ao introduzir LiveData, um número maior de desenvolvedores deve adotar o MVVM sem precisar entender o gerenciamento do ciclo de vida, vazamento de memória e falha. Mesmo que eu não tenha dúvida de que isso LiveDatanão é comparável RxJavaem termos de recursos e do poder que ele confere aos desenvolvedores, programação reativa e RxJavaé um conceito e uma ferramenta difícil de entender para muitos. Por outro lado, não creio LiveDataque seja um substituto para RxJava- simplesmente não pode -, mas uma ferramenta muito simples para lidar com um problema generalizado e controverso experimentado por muitos desenvolvedores.

** ATUALIZAÇÃO ** Adicionei um novo artigo aqui, onde expliquei como o uso incorreto do LiveData pode levar a resultados inesperados. RxJava pode vir para resgatar nessas situações



2
"por que foi introduzido quando RxJava poderia ter facilmente gerido o ciclo de vida, armazenando todas as assinaturas em um CompositeDispoable e depois descartá-los em onDestroy () do Activity" - LiveDatairia dispor na onStopverdade
arekolek

@arekolek do meu entendimento: mesmo para lidar com o CompositeDispoable, substituímos os métodos do ciclo de vida. Mas nos dados ao vivo, todos incluirão em uma única linha de código. Então, estamos economizando no mínimo 20 linhas de código.
Suresh

Podemos definir um baseFragment e definir o método Disposable [] subscriptions () a ser substituído por todos os fragmentos derivados, chame esse método em onCreateView e adicione o valor de retorno em CompositeDisposable, descarte isso em onDestroyView, sem esquecer.
Android2013

Não se trata apenas de descartar. Usando o RxJava, você precisa se desfazer do onStop, depois se inscrever novamente no onStart / onResume, lidar com as alterações de configuração e fazer várias outras coisas. É por isso que existem tantas falhas usando o RxJava. O LiveData lida com tudo isso, mas não é tão flexível quanto o RxJava.
user932178

24

Como você deve saber no ecossistema reativo, temos um Observável que emite dados e um Observador que assina (seja notificado) dessa emissão observável, nada de estranho é como funciona o chamado Padrão de Observador. Um Observável "grita" alguma coisa, o Observador é notificado de que o Observável grita algo em um determinado momento.

Pense LiveDatacomo um Observável que permite gerenciar os Observadores que estão em um activeestado. Em outros termos, LiveDataé um Observável simples, mas também cuida do ciclo de vida.

Mas vamos ver os dois casos de código que você solicita:

A) Dados ao vivo

B) RXJava

A) Esta é uma implementação básica do LiveData

1) você geralmente instancia o LiveData no ViewModel para manter a mudança de orientação (você pode ter LiveData que é somente leitura ou MutableLiveData que é gravável; portanto, você geralmente expõe fora da classe LiveData)

2) no OnCreatemétodo da Atividade principal (não no ViewModel), você "assina" um objeto Observer (geralmente um método aChanged)

3) você inicia o método observe para estabelecer o link

Primeiro o ViewModel(possui a lógica de negócios)

class ViewModel : ViewModel() { //Point 1

    var liveData: MutableLiveData<Int> = MutableLiveData()

}

E este é o MainActivity(o mais burro possível)

class MainActivity : AppCompatActivity() {

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)

        val ViewModelProvider= ViewModelProviders.of(this).get(ViewModel::class.java)

        ViewModelProvider.observe(this, Observer {//Points 2 and 3
            //what you want to observe
        })


        }
    }
}

B) Esta é a implementação básica do RXJava

1) você declara um Observável

2) você declara um observador

3) você assina o Observável com o Observador

Observable.just(1, 2, 3, 4, 5, 6) // Point 1

   .subscribe(new Subscriber() {    //Points 2 & 3
       @Override
       public void onCompleted() {
           System.out.println("Complete!");
       }

       @Override
       public void onError(Throwable e) {
       }

       @Override
       public void onNext(Double value) {
           System.out.println("onNext: " + value);
       }
    });

Em particular, LiveDataé usado com Lifecyclee freqüentemente com ViewModel(como vimos) componentes da arquitetura. De fato, quando LiveDatacombinado com um ViewModel permite que você mantenha atualizado em tempo real todas as alterações no Observer, para que os eventos sejam gerenciados em tempo real, quando necessário. Para usar LiveDataé altamente recomendável conhecer o conceito de ciclo de vida e os objetos relativos LifeCycleOwner / LifeCycle , também sugiro que você dê uma olhada em Transformações , se desejar implementar LiveDataem cenários da vida real. Aqui você encontra alguns casos de uso do ótimo commonsware .

Concluir basicamenteLiveDataé uma maneira simplificadaRXJavae elegante de observar alterações em vários componentes sem criar regras de dependência explícitas entre os componentes, para que você possa testar muito mais facilmente o código e torná-lo muito mais legível. RXJava, permite que você faça as coisas do LiveData e muito mais. Devido às funcionalidades estendidas do RXJava, você pode usar o LiveData para casos simples ou explorar todo o poder do RXJava e continuar usando os componentes da Arquitetura Android como o ViewModel , é claro que isso significa queRXJavapode ser muito mais complexo, basta pensar em centenas de operadores SwitchMap e Mapa de LiveData (no momento).

O RXJava versão 2 é uma biblioteca que revolucionou o paradigma Orientado a Objetos, adicionando a chamada maneira funcional de gerenciar o fluxo do programa.


4

LiveData é um subconjunto dos componentes da arquitetura do Android, desenvolvido pela equipe do Android.

Com os dados ativos e outros componentes da arquitetura, vazamentos de memória e outros problemas semelhantes são tratados pelos componentes da arquitetura. Uma vez que é desenvolvido pela equipe android, é o melhor para o Android. Eles também fornecem atualizações que lidam com novas versões do Android.

Se você deseja usar apenas no desenvolvimento de aplicativos Android, vá para os componentes da arquitetura Android. Caso contrário, se você quiser usar outro aplicativo Java, como aplicativo Web, aplicativos de desktop etc., use RxJava


Eu tentei esclarecer sua resposta. Se de alguma forma eu entrar em conflito com sua intenção original, fique à vontade para editar. Se o fizer, tente torná-lo mais claro que a revisão inicial. A última parte da sua resposta honestamente não fazia sentido.
Zoe

2

LiveDatacomo um detentor de dados e nada mais. Também podemos dizer que o LiveData é um consumidor consciente do ciclo de vida. LiveDataé altamente recomendável conhecer o conceito de ciclo de vida e os objetos relativos LifeCycleOwner / LifeCycle, você obtém recursos de transformação e fluxo para sua lógica de negócios e operação com reconhecimento de ciclo de vida para sua interface do usuário.

Rx é uma ferramenta poderosa que permite resolver problemas em um estilo declarativo elegante. Ele lida com opções do lado comercial ou operações da API de serviço


0

Comparar o LiveData com o RxJava é comparar maçãs com saladas de frutas.

Compare o LiveData ao ContentObserver e você está comparando maçãs com maçãs. LiveData efetivamente sendo um substituto compatível com o ciclo de vida do ContentObserver.

Comparar o RxJava ao AsyncTask ou qualquer outra ferramenta de segmentação é comparar saladas de frutas com laranjas, porque o RxJava ajuda mais do que apenas a segmentação.


0
  • LiveData é parcialmente igual a Rx Subject ou SharedRxObservable

  • O LiveData gerencia o ciclo de vida da assinatura, mas a assinatura do Rx Subject deve ser criada e descartada manualmente

  • LiveData não tem estado de terminação, mas o Rx Subject possui OnError e OnCompleted

Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.