Boas práticas e padrões · Arquitetura do código · 6 min de leitura
MVVM e MVI na interface
A tela só desenha um estado e envia ações; o ViewModel guarda o estado e aplica a lógica — fluxo de dados em uma só direção.
Arraste para o lado para ver o diagrama inteiro.
MVVM
O ViewModel expõe o estado observável (StateFlow, @Observable) e funções para os eventos da tela. Ele sobrevive a rotação de tela e não conhece a View. É o padrão recomendado pelo Android e muito usado com SwiftUI.
MVI
Leva o MVVM ao extremo: um único estado imutável por tela e todas as interações viram ações (sealed interface) processadas por um reducer. Vantagem: estado previsível, fácil de testar e de reproduzir bugs. Custo: mais código para telas simples.
Regras práticas
- Estado é imutável:
copy()em vez de mutar. - Eventos únicos (navegar, mostrar snackbar) não são estado persistente — trate com cuidado.
- ViewModel sem
Contextnem referências a Views.
No código
data class BuscaState(val termo: String = "", val carregando: Boolean = false, val itens: List<Repo> = emptyList(), val erro: String? = null)
sealed interface BuscaAcao {
data class Digitou(val termo: String) : BuscaAcao
data object Buscar : BuscaAcao
}
class BuscaViewModel(private val repo: RepoRepository) : ViewModel() {
private val _state = MutableStateFlow(BuscaState())
val state: StateFlow<BuscaState> = _state.asStateFlow()
fun enviar(acao: BuscaAcao) = when (acao) {
is BuscaAcao.Digitou -> _state.update { it.copy(termo = acao.termo) }
BuscaAcao.Buscar -> viewModelScope.launch {
_state.update { it.copy(carregando = true, erro = null) }
runCatching { repo.buscar(_state.value.termo) }
.onSuccess { itens -> _state.update { it.copy(carregando = false, itens = itens) } }
.onFailure { e -> _state.update { it.copy(carregando = false, erro = e.message) } }
}
}
} A tela só chama enviar(...) e desenha o state; testar é chamar ações e conferir o estado resultante.
Em resumo
- A tela desenha estado e envia ações.
- Fluxo unidirecional: previsível e testável.
- MVI: um estado imutável + ações selada.
- ViewModel não conhece a View nem o Context.
Vantagens e custos
- Estado único e reprodutível.
- Testes do ViewModel sem UI.
- Sobrevive a rotação e recriação.
- Mais código em telas triviais.
- Eventos únicos exigem cuidado extra.