IMPERATIVA Características principais • Ênfase em ações, enunciados ou comandos que mudam o estado (variáveis) de um programa • Uma série de instruções, com iterações, controle de fluxo, e tomadas de decisão • Traz complexidade quando temos que lidar com dados assíncronos • Traz complexidade quando precisamos utilizar requisições de forma complexa
REATIVA • Novo paradigma de programação orientado a eventos e propagação de mudanças • É visto como uma sequência de eventos • Busca facilitar o tratamento de eventos assíncronos, proporcionando: • Redução de código / Diminuição de código duplicado • Melhor controle de fluxo / Melhor controle dos erros Evento 1 Evento 2 Síncrono Evento 1 Evento 2 Assíncrono
• Curva de aprendizado: íngreme • Não se cobre caso demore pra aprender, é um novo paradigma • Depois que você entender o conceito e entender como pensar reativo tudo ficará mais fácil
• Quando precisamos lidar com requests encadeadas / complexas • Quando precisamos trabalhar com certa complexidade nos dados (manipulação e transformação dos dados) • Quando há necessidade de executar o trabalho em threads diferentes
DE OBSERVABLE val welcomeMessage = "Hello Arctouch” val observable = Observable.just(welcomeMessage) Obsevable é o item que queremos observar • Preço de passagens • Filmes • Restaurantes • Mensagens Para criar um observable:
DE UM OBSERVABLE JÁ CRIADO interface ApiInterface { @GET("images/search") fun searchCats(): Observable<List<Cat>> } @Query(value = "SELECT * FROM cat”) fun getCats(): Observable<List<Cat>> Requisições (Retrofit) Banco de dados (Room)
Características • Permitem manipular, filtrar, interagir, combinar, excluir / incluir, (…) fluxo de dados • Através do RxJava podemos manipular n vezes os dados emitidos • E o observador irá receber a informação pronta
Filmes Filmes de comédia Filmes de comédia lançados em 2019 Filtro Fluxo de Dados (stream) “n" transformações Resultado View Filtro Programação Reativa
DE OPERADORES • Cada operador retorna um tipo que permite encadear operadores • Chamamos esta composição de stream ou chain ou cadeia • Isso permite que aplicamos uma série de operações em um determinado observable, a fim de atingirmos o que desejamos val observableTake = Observable.just(1, 2, 3, 4, 5) .take(3) .filter(object : Predicate<Int> { override fun test(t: Int): Boolean { return t < 3 } }) observableTake.subscribe(observer) Log take and filter: Result = 1 Log take and filter: Result = 2
• Transforma itens obtidos por um observable em observables e empacota eles em um único observable • Permite encadear estruturas diferentes, porém que possuem ou agregam o mesmo propósito • As transformações consecutivas não requerem alteração no modelo ou API
ON • Recebe um scheduler como parâmetro e retorna um observable (permitindo que façamos chain com eles também) • Representa em qual thread queremos que o observable esteja quando for inscrito (quando o subscribe for chamado) • Sua ordem na chain é indiferente • Schedulers: • Computation - operações, cálculos • Io - operações network e acesso a banco de dados • Single - roda tudo numa única thread • Trampoline - roda na thread atual / execução siga uma ordem • (…)
ON • Permite facilmente mover o trabalho executado entre diferentes threads • Diferente do subscribeOn, a ordem dos ObserveOn altera a thread em que o código será executado • Tudo que estiver abaixo do observeOn será executado na Thread indicada Observable.just("Hello:") .subscribeOn(Schedulers.computation()) .operador_1() {código A} .operador_2() {código B} .observeOn(schedulers.io()) .operador_3() {código C} .operador_4() {código D} .observeOn(schedulers.single()) .operador_5() {código E} .observeOn(AndroidSchedulers.mainThread()) .subscribe { Log.i("Log observeOn”, "Result $it") } Código Thread A e B Computation C e D IO E Single RESULTADO Main Thread
• Interface que permite parar de ouvir as emissões, e assim liberando qualquer recurso que esteja sendo segurado. Possui um método chamado dispose() • O Disposable tem o poder de dizer para a aplicação: “Olha agora não preciso mais deste processo" • Se não chamamos o método dispose() permitimos (em alguns casos) que o processo não termine, podendo causar memory leaks • CompositeDisposable - é um objeto que armazena e manipula disposables
PARA PRÓXIMOS ESTUDOS • Quando, como e Onde usar RxJava? • Requests que tragam certa complexidade • Quando precisamos unir dados de uma request: exemplo filmes + gênero • Quando precisamos mover o trabalho realizado entre threads • Quando precisamos trabalhar com certa complexidade nos dados • Quando precisamos manipular o dado a ponto que seja muito complexo fazê-lo de outra forma • Não mate uma formiga com uma bazuca • Considere utilizar Kotlin Coroutines para • chamadas simples • Trabalhos menos complexos executados em outras threads • Processamento de streams