Article image

JS

JOAO SANTOS24/11/2023 10:55
Compartilhe

Introdução ao padrão MVI no desenvolvimento Android

    Afinal o que é o padrão MVI? 

    MVI é um dos mais novos padrões de arquitetura para Android, inspirado na natureza unidirecional e cíclica da estrutura Cycle.js

    O MVI funciona de maneira muito diferente em relação aos padrões MVC, MVP ou MVVM.

    Basicamente consiste em três principais componentes:  

    Model : representa o estado. É representado por uma classe imutável para garantir que o fluxo de dados seja unidirecional e que o estado não seja alterado em nenhum outro lugar no aplicativo, se tornando a única fonte de verdade [single source of truth]

    View : representa a camada de interface com o usuário.  Entrega as ações do usuário e atualiza a interface refletindo as mudanças de estados recebidas. 

    Intent : são as ações desencadeados pelo usuário.  [Não confunda com o Android Intent.] São capturadas por meio da interação do usuário com a View.

    Entendendo o Fluxo de dados no MVI 

    O

    1. A View é renderizada com base no estado inicial da classe UiState

    2. Quando uma interação do usuário ocorre, a View envia essa ação para a viewModel.

    3. A ação recebida gera um evento que é processado e seu resultado deste processamento emite um novo estado. 

    4. O novo estado é imediatamente refletido na View.  

    Representando Estados

     data class LoginUiStates( 
     val isSuccessLogin : Boolean = false, 
     val allFieldsAreFilled : Boolean = false, 
     val name:String = "", 
     val pass:String = "", 
     val isNameError : Boolean = false, 
     val nameErrorHint : String = "Digite seu nome", 
     val isPassError : Boolean = false, 
     val passErrorHint : String = "A senha deve conter 4 dígitos"
    ) 
    

    Representando Eventos

    sealed class LoginEvent { 
     data class ValidateNameField(val name: String) : LoginEvent() 
     data class ValidatePassField(val pass: String) : LoginEvent() 
     object ValidateLogin : LoginEvent() 
    } 
    

    Exemplo de uma implementação na viewModel usando flow: 

    private val _uiState: MutableStateFlow<LoginUiStates> = 
     MutableStateFlow(LoginUiStates.Empty) 
    
    var uiSTate: StateFlow<LoginUiStates> = _uiState  
    
    private val actions = MutableSharedFlow<LoginEvent>()  
    
    

    A cada evento recebido nossa View invoca o método onEvent da viewModel :

     fun onEvent(event: LoginEvent) { 
     viewModelScope.launch { 
      actions.emit(event) 
     } 
     }  
    

    A cada evento emitido nossa viewModel desencadeia uma ação, e a partir do resultado atualizamos o estado: 

    private fun handleEvents() { 
     viewModelScope.launch { 
      actions.collect { event -> 
          when (event) { 
              is LoginEvent.ValidateLogin -> validatingLogin() 
              is LoginEvent.ValidateNameField -> validateNameField(event) 
              is LoginEvent.ValidatePassField -> validatePassField(event)
          } 
      } 
    } 
    } 
    

    Ação desencadeada por um evento

    private fun validatePassField(event: LoginEvent.ValidatePassField) { 
     _uiState.update { it.copy(pass = event.pass) } 
     if (event.pass.isNotEmpty() && event.pass.length > 4)  
    _uiState.update { it.copy(isPassError = false) } 
     else _uiState.update { it.copy(isPassError = true) } 
    } 
    

    Benefícios do MVI com Jetpack Compose 

    1. Separação de responsabilidades: O MVI divide as responsabilidades entre modelo, view e viewModel, tornando o código mais modular e fácil de entender. 

    2. Testabilidade aprimorada: Como o estado é imutável e a lógica de negócio é isolada na ViewModel, os testes se tornam mais simples e confiáveis. 

    3. Previsibilidade do fluxo de dados: O fluxo unidirecional do MVI garante que o estado seja atualizado de maneira consistente, tornando mais fácil rastrear o fluxo de dados no aplicativo. 

     4. Reprodutibilidade do estado: Com o MVI, o estado do aplicativo é reprodutível, o que significa que é possível reproduzir determinados estados para depuração e correção de bugs e testes de UI. 

    Conclusão 

    O padrão MVI oferece uma ótima opção de padrão arquitetural quando utilizamos o Jetpack Compose. Ele ajuda a separar as responsabilidades, tornar o código mais testável e oferecer um fluxo de dados previsível.

    Link : https://github.com/JoaoSantosBH/MoviesCompose

    Referencias: 

    https://medium.com/swlh/mvi-architecture-with-android-fcde123e3c4a 

    https://www.kodeco.com/817602-mvi-architecture-for-android-tutorial-getting-started

      

    Compartilhe
    Comentários (0)