Photo by Fabian Grohs on Unsplash

Aplicando Mobx, Chopper, JSON_serializable e Get.It em uma aplicação Flutter MVVM e Clean Architecture.

Guilherme Rocha
Usemobile
Published in
6 min readJul 30, 2020

--

Sendo um desenvolvedor Android me aventurando nesse mundo do Flutter, estou tentando sempre deixar as coisas o mais próximas possíveis do que já estava acostumado. Ou seja, procurando libs e arquiteturas que vão deixar meus projetos em Flutter com uma estrutura parecida com os que eu faço no Android nativo.

Por isso, escrevo esse artigo para compartilhar o fluxo de login de um aplicativo em Flutter composto por uma união de bibliotecas poderosas que tornaram o desenvolvimento nesse Framework mais próximo ao Android nativo e mais prático.

Vou apresentar as bibliotecas e não se preocupe se os conceitos ficarem um pouco nebulosos. A ideia é começar por eles e depois eu vou mostrar na prática a implementação 😊.

Conhecendo as bibliotecas

Mobx

É uma lib que gerencia o estado da aplicação. Se você que está lendo esse artigo já teve algum contato com Flutter e conhece o famoso setState(), você vai perceber que o uso dessa biblioteca deve remover qualquer incidência desse método.

Com o Mobx vamos gerenciar as alterações na view e criaremos a ViewModel usando os três conceitos básicos que constroem a lib: Observables, Actions e Reactions. Aqui está o link da documentação oficial do Mobx com a definição de todos esses termos.

Chopper

O Chopper é uma biblioteca para comunicação Http que foi inspirada no Retrofit. A estrutura de definição dos endpoints e dos modelos de body e result se assemelha bastante com a biblioteca do Android. A ideia de usar essa lib é justamente para não ter que fazer na mão todas as tratativas de erros, interceptors, adição de headers, loggers etc.

json_serializable

Essa é uma lib que vai trabalhar junto ao Chopper para tratar os modelos usados na comunicação. O json_serializable será responsável por transformar (serializar) o dados de forma a atender os requisitos especificados pela API. Com ela vamos converter os dados de json para objetos em dart e vice-versa.

Get_It

O get_it é uma biblioteca de service locator que foi usada no projeto para fazer o papel de injeção de dependência (DI). Ela é responsável por prover as ViewModels, os UseCases, repositórios e serviço de comunicação. É uma ferramenta de fácil entendimento e que requer pouca implementação. É ideal para quem está começando a estudar os conceitos de DI.

Antes de começar o passo a passo do código, é válido pontuar que grande parte das bibliotecas aqui utilizadas fazem uso de geração de código. Então é comum aparecer classes como:

A classe que contém o “.g.dart” é a classe gerada automaticamente e, portanto, não deve ser alterada manualmente. Para que esses códigos sejam gerados, existem alguns comandos que são executados no terminal, sendo o principal deles o:

¬flutter packages pub run build_runner watch

Esse comando fica “escutando” as alterações feitas nas classes e vai gerando o código a partir delas. Guarde-o com você.

Chega de resenha e vamos ao código!

O primeiro passo é adicionar as dependências necessárias

Se você está utilizando esse artigo como um tutorial, recomendo, além de continuar a leitura do passo a passo, baixar aqui o código completo.

Agora começaremos com a nossa login_viewmodel.

Ela será composta pelos observables responsáveis por gerenciar o estado da view, são eles:

Também temos as funções que preenchem esses observables que são as actions.

Um ponto muito importante é validar se os campos satisfazem as condições mínimas para que a função de login seja chamada, então por isso criamos os computeds.

Como observado aqui no “loginPressed”, é possível unificar mais de um computed. O que está sendo feito nesse método é que, somente quando todas as condições forem satisfeitas, a função de clique do login será retornada.

Podemos ver aqui que essa função recebe um UserModel, este que será tratado mais pra frente na nossa view.

Feito isso, partiremos para a implementação da nossa tela de login

Neste artigo eu não vou focar em construção de layout então teremos uma telinha bem simples.

Os textFields de login e senha precisam ter os seus campos de onChange definidos. Com eles serão chamados os métodos correspondentes na ViewModel.

Com isso, podemos garantir que sempre que um campo for alterado na view, a ViewModel receberá essa alteração.

O botão de LOGIN deve conter como função de clique aquela que definimos lá na ViewModel, que é retornada pelos @computed. Além disso ele também considera a isLoading da ViewModel para controlar se vai exibir o progressIndicator ou não.

É importante notar que o botão está dentro de um widget Observer, que é uma anotação do Mobx que garante que aquele elemento vai ser alterado de acordo com as reações da biblioteca. Ou seja, no caso do botão de login, quando as condições de email e senha correta forem satisfeitas, a ViewModel retornará a função de clique para esse botão. Então é necessário que este fique “escutando” as alterações que a ViewModel envia. Por isso o widget em questão.

Por fim, precisamos verificar aquele UserModel que recebemos lá na função de loginUser. A ideia é: quando o user não for mais nulo, o app vai navegar para a tela Home. Para isso vamos utilizar o Reaction do Mobx.

Agora vamos passar para a implementação do Chopper

Primeiro é preciso definir o Chopper Client, que vai conter a baseUrl, o service, os interceptors e o converter.

O HttpLoggingInterceptor é um interceptor que serve para printar as requisições e as respostas no log da IDE. Dessa forma podemos acompanhar tudo que enviamos e recebemos para o servidor.

É importante focarmos no converter, porque é ele que garante que nossas classes de modelos serão serializadas corretamente de acordo com o retorno da API. Mais a frente vamos tratar especificamente dele.

O próximo trecho de código é a parte em que declaramos os nossos endpoints. Mostramos ao Chopper o caminho da requisição, quais os tipos da resposta e dos parâmetros e também criamos a instância do serviço. Para quem está familiarizado com o Retrofit, vai perceber que o código se assemelha muito.

Para tratar a response e o body do login que declaramos vamos usar o json_serializable

Começaremos adicionando a anotação @JsonSerializable na classe que será serializada.

Após isso, vamos declarar os métodos fromJson e toJson.

Vale lembrar que essa biblioteca usa geração de código, então é ela que vai fazer o trabalho sujo pra gente.

Voltando um pouco ao ChopperClient, precisamos “avisar” a ele quais são as classes que serão convertidas de json para objetos em Dart.

Por fim, falaremos do get_it

Como mencionado anteriormente, é uma biblioteca de implementação muito fácil e intuitiva. Primeiramente vamos criar o método setUpLocator. Nele vamos registrar as instâncias de todos os módulos que vamos prover para a aplicação, como ViewModels, UseCases, repositórios e serviço do Chopper.

Repare que alguns módulos dependem de outros. Por isso que dentro dos seus próprios construtores o serviceLocator é chamado procurando a instância de tal dependência.

Por fim, basta chamarmos o serviceLocator para passar a classe que precisamos invocar. Vou listar alguns exemplos abaixo:

Esse projeto serviu para unir conceitos de Clean Architecture e o uso de bibliotecas que me deixaram mais próximos ao desenvolvimento Android. Dessa forma, se você clonar o repositório e seguir o tutorial em questão, terá em mãos um projeto inicial poderoso e cheio de conceitos importantes.

Então é isso! Agradeço a você que ficou até aqui e espero que o conteúdo desse artigo tenha sido proveitoso. Aguardo críticas e sugestões para continuar escrevendo sobre Flutter, Android e minhas experiências com desenvolvimento mobile. Aproveite para deixar uma palminha!

Obrigado e até mais!

--

--