SlideShare uma empresa Scribd logo
MVI + Flow
Uma arquitetura reativa com fluxo unidirecional
1
• Roque Buarque Junior
• Desenvolvedor Android
• Berlim - Alemanha
• Sharenow
• Twitter @roqbjr
Sobre mim :)
2
O que esperar?
• Entender a arquitetura MVI
• Visão geral de outras arquiteturas
• Como lidar com estados e eventos
• Exemplo de código com Flow
• Implementar uma feature juntos
3
O que não esperar?
• Coroutines Scopes/Jobs
• Testes integrados
4
O que é MVI?
M
Model estado imutável, única fonte
de verdade.
5
O que é MVI?
V View que representa a UI.
6
O que é MVI?
I
Intent, não é do Android, representa a intenção
de performar uma ação do usuário ou do app.
7
MODEL
INTENTVIEW
Action Creator
Reducer
Guard
8
Case
• Eventos/Intent
• Incrementar
• Decrementar
• Estados
• Loading
• Content
• Message
9
MVI
view(model(intent(
)))
10
MVI
Eventos Estados
11
INTENT
Jogo de palavras
MODEL
VIEW MODEL
STATEPRESENTER
INTERACTOR USE CASE
12
O que as arquiteturas tem em comum?
MVP MVVM MVI
Model
13
class CounterPresenter {
private lateinit var view: CounterView
private val repository = CounterRepository
fun start(view: CounterView) { … }
fun increase() {
view.loading(true)
repository.increase(object : CounterCallback{
override fun onSuccess(value: Int) {
view.loading(false)
view.updateCounter(value)
}
override fun onError(throwable: Throwable) {
view.loading(false)
view.error(throwable.message ?: "error")
}
})
}
fun decrease(){ … }
}
Presenter
14
override fun updateCounter(value: Int) {
txtCounter.text = value.toString()
}
override fun loading(isLoading: Boolean) {
progressBar.isVisible = isLoading
}
override fun error(msg: String) {
txtCounter.text = msg
}
View
15
MVP - Stateless
ModelPresenterView
Input Modify
Update
16
ViewModel
class CounterViewModel: ViewModel() {
private val repository = CounterRepository
val error = MutableLiveData<String>()
val loading = MutableLiveData<Boolean>()
val content = MutableLiveData<Int>()
fun increase(){
loading.value = true
repository.increase(object : CounterCallback{
override fun onSuccess(counter: Counter) {
loading.value = false
content.value = counter.value
}
override fun onError(throwable: Throwable) {
loading.value = false
error.value = throwable.message ?: "error"
}
})
}
}
17
View
class CounterViewModel: ViewModel() {
private val repository = CounterRepository
val error = MutableLiveData<String>()
val loading = MutableLiveData<Boolean>()
val content = MutableLiveData<Int>()
fun increase(){
loading.value = true
repository.increase(object : CounterCallback{
override fun onSuccess(counter: Counter) {
loading.value = false
content.value = counter.value
}
override fun onError(throwable: Throwable) {
loading.value = false
error.value = throwable.message ?: "error"
}
})
}
}
private fun setupObserver() {
viewModel.content.observe(this, Observer {
txtCounter.text = it.toString()
})
viewModel.error.observe(this, Observer {
txtCounter.text = it
})
viewModel.loading.observe(this, Observer {
progressBar.isVisible = it
})
}
18
MVVM - Stateful
Model
View Model
ViewState
View
Input
Modify
Observe/Notify
19
O que é o Model?
data class CounterModel(
val value: Int?= null,
val isLoading: Boolean,
val msg: String? = null
)
20
Model
Loading Error Content
Model/State
21
Como lidar com estados?
22
Quais são os desafios?
Mutabilidade Múltiplos estados Sincronização
24
Mutabilidade
25
ViewModel
class CounterViewModel : ViewModel() {
private val repository = CounterRepository
private val _model = MutableLiveData<CounterModel>()
val model: LiveData<CounterModel> = _model
fun increase() {
_model.value = CounterModel(isLoading = true)
repository.increase(object : CounterCallback {
override fun onSuccess(counter: Counter) {
_model.value = CounterModel(isLoading = false,
value = counter.value)
}
override fun onError(throwable: Throwable) {
_model.value = CounterModel(
isLoading = false,
msg = throwable.message ?: "error"
)
}
})
}
}
28
View
private fun setupObserver() {
viewModel.model.observe(this, Observer { model ->
progressBar.isVisible = model.isLoading
val count = model.value?.toString() ?: ""
txtCounter.text = count
model.msg?.let {
txtCounter.text = it
}
})
}
29
Múltiplos estados
30
O que aconteceria?
CounterModel(
value: Int? = 2, //Mostrar text com contador
isLoading:Boolean = true, //Mostrar loading
msg: String? = “Algo deu MUITO errado!” //Mostrar erro
)
31
Perigo!
Loading
Empty
Notification
32
Data class único
Imutabilidade, uma fonte da verdade.
Maneira mais simples
Tudo dentro de uma classe única
Regra na View
Múltiplos estados
override fun render(model: CounterModel) {
progressBar.isVisible = model.isLoading
val count = model.value?.toString() ?: ""
txtCounter.text = count
model.msg?.let {
txtCounter.text = it
}
}
34
Hierarquia de
sealed class
Imutabilidade, uma fonte de verdade.
Cada classe representa uma implementação do
estado
Cada item pode ter seus próprios campos
Utiliza object evitando criar mais de uma
instância
Evita enviar o mesmo estado mais de uma vez
no caso de object
sealed class CounterState {
data class Content(
val value: Int
) : CounterState()
object Loading : CounterState()
data class Error(
val msg: String
) : CounterState()
}
35
View
private fun setupObserver() {
viewModel.state.observe(this, Observer { state ->
render(state)
})
}
private fun render(state: CounterState) {
when (state) {
is CounterState.Loading -> progressBar.isVisible = true
is CounterState.Content -> {
progressBar.isVisible = false
txtCounter.text = state.value.toString()
}
is CounterState.Error -> {
progressBar.isVisible = false
txtCounter.text = state.msg
}
}
}
36
ViewModel
class CounterViewModel : ViewModel() {
private val repository = CounterRepository
private val _state = MutableLiveData<CounterState>()
val state: LiveData<CounterState> = _state
fun increase() {
_state.value = CounterState.Loading
repository.increase(object : CounterCallback {
override fun onSuccess(counter: Counter) {
_state.value = CounterState.Content(counter.value)
}
override fun onError(throwable: Throwable) {
_state.value = CounterState.Error(
throwable.message ?: "error"
)
}
})
}
}
37
Sincronizar estados
Interactor
API
Transformação
1
View
isEnable
isVisible
Text
3
View Model
Loading
Error
Content
2
State
38
Máquina de estados
39
State Machine/ Máquina de estado
Jogando
ParadoAcabado
Pause
ResumeComeçar
Morreu
40
Consegue quebrar uma tela em vários estágios
Quando? Onde? Como?
Visão do fluxo inteiro
Fácil de identificar qual estágio é responsável por cada requisição
Testável
Sustentável/Maintainable
Estável
41
State Machine/ Máquina de estado
State Machine/ Máquina de estado
Loading
Message
Content
Error
Success
???
Action/AçãoState/Estado
Executing
Even
t
42
MVI
Loading
Increase
Content/
Message
Executing
Success/Error
43
Estágio/Stage
Loading
Transição
Increase
44
Components
Event
Action
State
SyncState
Intent do MVI,
Uma intenção do usuário ou do app, e.g. click no botão.
A ação que minha view deve executar, por exemplo execution/loading
Combinação entre meu retorno/data da API com o meu SyncState
Estado atual da minha view/tela
45
Components
Action
Creator
Reducer
Guard
Recebe um evento, conecta meu repositório e cria uma ação para o meu reducer transformar
em novo estado
Recebe o estado atual da view e uma nova ação e devolve um novo estado dependendo do guard
Valida o boolean recebido do reducer para decidir se vai prosseguir
46
MVI
Event
New
State
Action
Creato
r
Event/Increase
Api
Action/Executing
Reduc
er
(Event) -> Action (CurrentState, Action) -> NewState
Guard
Content/Execution Loading
49
State Machine/ Máquina de estado
Loading
Message
Content
Error
Success
???
Action/AçãoState/Estado
Executing
Even
t
50
MVI
Event
New
State
Action
Creato
r
Event/Increase
Api
Request
Result
Action/Success
Reduc
er
(Event) -> Action (CurrentState, Action) -> NewState
Guard
Message/Success
51
State Machine/ Máquina de estado
Loading
Message
Content
Error
Success
???
Action/AçãoState/Estado
Executing
Even
t
52
Reducer
• Concentra as mudanças de estado em somente um lugar
• Fácil de debugar
• MUITO fácil de testar
• Vai concatenar seu estado atual no seu novo estado.
54
Como lidar com eventos?
55
Eventos
View Repo
1
2
56
Eventos
View Repo
1
2
Incrementar
Decrementar
1
0
2
1
1 + 1 = 2
2 - 1 = 1
1 - 1 = 0
0 + 1 = 1
Esperado Encontrado
57
Maneira mais fácil de enfileirar eventos
58
Caso real
59
60
Eventos
View Repo12
61
Fluxo unidirecional
Event
Process
Result
State
Repository
ViewModel
View
63
Fluxo unidirecional
Event
Process
State
Repository
ViewModel
View
Action Creator
Reducer Guard
(Event) -> Action
(State, Action) -> State
64
Flow
67
Emitir e Coletar
flow<Event> {
emit(CounterEvent.Increase)
}
scope.launch {
state.collect { state ->
render(state)
}
}
70
Flow outros operadores
fun getActionFlow(): LiveData<CounterAction> =
fetchAsFlow()
.flatMapLatest { secondNetworkCallThatDependsOnFirst() }
.map { CounterAction.Error("deu ruim") }
.onEach { }
.take(2)
.filter { }
.catch { emit(CounterAction.Error("erro inesperado") }
.onCompletion { }
.flowOn(Dispatchers.IO)
.asLiveData()
80
State flow
State-Holder que emite o valor atual
MutableStateFlow para alterar o valor
Pede um valor inicial
Muito util deixar na view model para sobreviver a mudanças de configuração
HOT - Diferente de um flow builder o StateFlow vai continuar emitindo
81
Shared flow
Compartilhar emissões entre mais de um coletor
É um hot flow
Guarda um cache
Da um replay desse cache para novos coletores
Substitui o BroadcastChannel
82
Ligando os pontos
Reducer State
SyncState
Action Creator
Event
Guard
84
Cadeia
Event/Increase
Action/Executing
State/Loading
ViewModel - Process
View
Action Creator
Reducer/Guard
Content
StateFlow
CacheRepositório
Novo
Estado
95
Evento e Estado
private val event = MutableSharedFlow<Event>()
val state: StateFlow<State> = toState()
96
Evento e Estado
private val event = MutableSharedFlow<Event>()
val state: StateFlow<State> = toState()
suspend fun process(event: Flow<Event>) {
event.collect {
this.event.emit(it)
}
}
97
toState
private fun toState(): StateFlow<State> {
}
98
Evento
private fun toState(): StateFlow<State> {
return event
.onEach { Log.d(TAG, "Event $it") }
}
99
Action
private fun toState(): StateFlow<State> {
return event
.onEach { Log.d(TAG, "Event $it") }
.flatMapConcat { event-> action(event) }
.distinctUntilChanged()
.onEach { Log.d(TAG, "Action $it") }
}
100
Reducer/New State
private fun toState(): StateFlow<State> {
return event
.onEach { Log.d(TAG, "Event $it") }
.flatMapConcat { event-> action(event) }
.distinctUntilChanged()
.onEach { Log.d(TAG, "Action $it") }
.map {action-> reducer(state.value, action) }
.onEach { Log.d(TAG, "State $it") }
}
101
State flow
private fun toState(): StateFlow<State> {
return event
.onEach { Log.d(TAG, "Event $it") }
.flatMapConcat { event-> action(event) }
.distinctUntilChanged()
.onEach { Log.d(TAG, "Action $it") }
.map {action-> reducer(state.value, action) }
.onEach { Log.d(TAG, "State $it") }
.onCompletion { Log.d(StateViewModel::class.java.name, "onCompletion for $state") }
.stateIn(viewModelScope, SharingStarted.Lazily, initialState)
}
102
Implementação de
feature
103
Deu para entender
um pouco de MVI?
104
Fontes
MVI
http://hannesdorfmann.com/android/mosby3-mvi-1
https://zsmb.co/designing-and-working-with-single-view-states-on-android/
Flow
https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines.flow/
105
Dev vai longe!
106
Obrigado!
107
Perguntas e
Respostas
108

Mais conteúdo relacionado

Semelhante a Entendento Arquitetura MVI + Flow

Minicurso kotlin UTFPR
Minicurso kotlin UTFPR Minicurso kotlin UTFPR
Minicurso kotlin UTFPR
Rafael Reynoud Benetti
 
Minicurso kotlin no desenvolvimento mobile - UTFPR
Minicurso kotlin no desenvolvimento mobile - UTFPRMinicurso kotlin no desenvolvimento mobile - UTFPR
Minicurso kotlin no desenvolvimento mobile - UTFPR
Lucas Antonio Ramos Sartori
 
Angular + Redux (ngRx)
Angular + Redux (ngRx)Angular + Redux (ngRx)
Angular + Redux (ngRx)
Loiane Groner
 
Desmistificando o cairngorm
Desmistificando o cairngormDesmistificando o cairngorm
Desmistificando o cairngorm
Eric Cavalcanti
 
Mock Objects
Mock ObjectsMock Objects
Mock Objects
elliando dias
 
React + Flux (Alt)
React + Flux (Alt)React + Flux (Alt)
React + Flux (Alt)
Cezar Luiz
 
Hello vue
Hello vueHello vue
Hello vue
Gabriel Colombo
 
DDD > Experiências
DDD > ExperiênciasDDD > Experiências
DDD > Experiências
Giovanni Bassi
 
aula09-redux-firebase-auth.pdf
aula09-redux-firebase-auth.pdfaula09-redux-firebase-auth.pdf
aula09-redux-firebase-auth.pdf
BrunoTorres978388
 
Projetos reativos com Angular, RxJS e Redux (ngRx)
Projetos reativos com Angular, RxJS e Redux (ngRx)Projetos reativos com Angular, RxJS e Redux (ngRx)
Projetos reativos com Angular, RxJS e Redux (ngRx)
Loiane Groner
 
Teste de Integracao com DbUnit e JStryker
Teste de Integracao com DbUnit e JStrykerTeste de Integracao com DbUnit e JStryker
Teste de Integracao com DbUnit e JStryker
Washington Botelho
 
Spring + Tapestry Um novo paradigma de desenvolvimento web
Spring + Tapestry Um novo paradigma de desenvolvimento webSpring + Tapestry Um novo paradigma de desenvolvimento web
Spring + Tapestry Um novo paradigma de desenvolvimento web
elliando dias
 
Java 05 Oo Basica
Java 05 Oo BasicaJava 05 Oo Basica
Java 05 Oo Basica
Regis Magalhães
 
Introdução à análise orientada a objetos parte 1
Introdução à análise orientada a objetos parte 1Introdução à análise orientada a objetos parte 1
Introdução à análise orientada a objetos parte 1
ariovaldodias
 
Introdução à análise orientada a objetos parte 1
Introdução à análise orientada a objetos parte 1Introdução à análise orientada a objetos parte 1
Introdução à análise orientada a objetos parte 1
ariovaldodias
 
TDC - Introdução ao Actor Model com Microsoft Orleans
TDC - Introdução ao Actor Model com Microsoft OrleansTDC - Introdução ao Actor Model com Microsoft Orleans
TDC - Introdução ao Actor Model com Microsoft Orleans
Fabio Gouw
 
Introdução a jQuery
Introdução a jQueryIntrodução a jQuery
Introdução a jQuery
Rodrigo Aramburu
 
Design Patterns na Programação de Jogo
Design Patterns na Programação de JogoDesign Patterns na Programação de Jogo
Design Patterns na Programação de Jogo
Bruno Cicanci
 
Introdução ao jquery
Introdução ao jqueryIntrodução ao jquery
Introdução ao jquery
Yuri Costa
 
Qualidade de Software: Escrevendo Código Limpo
Qualidade de Software: Escrevendo Código LimpoQualidade de Software: Escrevendo Código Limpo
Qualidade de Software: Escrevendo Código Limpo
Lidiane Taquehara
 

Semelhante a Entendento Arquitetura MVI + Flow (20)

Minicurso kotlin UTFPR
Minicurso kotlin UTFPR Minicurso kotlin UTFPR
Minicurso kotlin UTFPR
 
Minicurso kotlin no desenvolvimento mobile - UTFPR
Minicurso kotlin no desenvolvimento mobile - UTFPRMinicurso kotlin no desenvolvimento mobile - UTFPR
Minicurso kotlin no desenvolvimento mobile - UTFPR
 
Angular + Redux (ngRx)
Angular + Redux (ngRx)Angular + Redux (ngRx)
Angular + Redux (ngRx)
 
Desmistificando o cairngorm
Desmistificando o cairngormDesmistificando o cairngorm
Desmistificando o cairngorm
 
Mock Objects
Mock ObjectsMock Objects
Mock Objects
 
React + Flux (Alt)
React + Flux (Alt)React + Flux (Alt)
React + Flux (Alt)
 
Hello vue
Hello vueHello vue
Hello vue
 
DDD > Experiências
DDD > ExperiênciasDDD > Experiências
DDD > Experiências
 
aula09-redux-firebase-auth.pdf
aula09-redux-firebase-auth.pdfaula09-redux-firebase-auth.pdf
aula09-redux-firebase-auth.pdf
 
Projetos reativos com Angular, RxJS e Redux (ngRx)
Projetos reativos com Angular, RxJS e Redux (ngRx)Projetos reativos com Angular, RxJS e Redux (ngRx)
Projetos reativos com Angular, RxJS e Redux (ngRx)
 
Teste de Integracao com DbUnit e JStryker
Teste de Integracao com DbUnit e JStrykerTeste de Integracao com DbUnit e JStryker
Teste de Integracao com DbUnit e JStryker
 
Spring + Tapestry Um novo paradigma de desenvolvimento web
Spring + Tapestry Um novo paradigma de desenvolvimento webSpring + Tapestry Um novo paradigma de desenvolvimento web
Spring + Tapestry Um novo paradigma de desenvolvimento web
 
Java 05 Oo Basica
Java 05 Oo BasicaJava 05 Oo Basica
Java 05 Oo Basica
 
Introdução à análise orientada a objetos parte 1
Introdução à análise orientada a objetos parte 1Introdução à análise orientada a objetos parte 1
Introdução à análise orientada a objetos parte 1
 
Introdução à análise orientada a objetos parte 1
Introdução à análise orientada a objetos parte 1Introdução à análise orientada a objetos parte 1
Introdução à análise orientada a objetos parte 1
 
TDC - Introdução ao Actor Model com Microsoft Orleans
TDC - Introdução ao Actor Model com Microsoft OrleansTDC - Introdução ao Actor Model com Microsoft Orleans
TDC - Introdução ao Actor Model com Microsoft Orleans
 
Introdução a jQuery
Introdução a jQueryIntrodução a jQuery
Introdução a jQuery
 
Design Patterns na Programação de Jogo
Design Patterns na Programação de JogoDesign Patterns na Programação de Jogo
Design Patterns na Programação de Jogo
 
Introdução ao jquery
Introdução ao jqueryIntrodução ao jquery
Introdução ao jquery
 
Qualidade de Software: Escrevendo Código Limpo
Qualidade de Software: Escrevendo Código LimpoQualidade de Software: Escrevendo Código Limpo
Qualidade de Software: Escrevendo Código Limpo
 

Último

Segurança Digital Pessoal e Boas Práticas
Segurança Digital Pessoal e Boas PráticasSegurança Digital Pessoal e Boas Práticas
Segurança Digital Pessoal e Boas Práticas
Danilo Pinotti
 
Logica de Progamacao - Aula (1) (1).pptx
Logica de Progamacao - Aula (1) (1).pptxLogica de Progamacao - Aula (1) (1).pptx
Logica de Progamacao - Aula (1) (1).pptx
Momento da Informática
 
Manual-de-Credenciamento ANATER 2023.pdf
Manual-de-Credenciamento ANATER 2023.pdfManual-de-Credenciamento ANATER 2023.pdf
Manual-de-Credenciamento ANATER 2023.pdf
WELITONNOGUEIRA3
 
História da Rádio- 1936-1970 século XIX .2.pptx
História da Rádio- 1936-1970 século XIX   .2.pptxHistória da Rádio- 1936-1970 século XIX   .2.pptx
História da Rádio- 1936-1970 século XIX .2.pptx
TomasSousa7
 
Certificado Jornada Python Da Hashtag.pdf
Certificado Jornada Python Da Hashtag.pdfCertificado Jornada Python Da Hashtag.pdf
Certificado Jornada Python Da Hashtag.pdf
joaovmp3
 
TOO - TÉCNICAS DE ORIENTAÇÃO A OBJETOS aula 1.pdf
TOO - TÉCNICAS DE ORIENTAÇÃO A OBJETOS aula 1.pdfTOO - TÉCNICAS DE ORIENTAÇÃO A OBJETOS aula 1.pdf
TOO - TÉCNICAS DE ORIENTAÇÃO A OBJETOS aula 1.pdf
Momento da Informática
 
DESENVOLVIMENTO DE SOFTWARE I_aula1-2.pdf
DESENVOLVIMENTO DE SOFTWARE I_aula1-2.pdfDESENVOLVIMENTO DE SOFTWARE I_aula1-2.pdf
DESENVOLVIMENTO DE SOFTWARE I_aula1-2.pdf
Momento da Informática
 
PRODUÇÃO E CONSUMO DE ENERGIA DA PRÉ-HISTÓRIA À ERA CONTEMPORÂNEA E SUA EVOLU...
PRODUÇÃO E CONSUMO DE ENERGIA DA PRÉ-HISTÓRIA À ERA CONTEMPORÂNEA E SUA EVOLU...PRODUÇÃO E CONSUMO DE ENERGIA DA PRÉ-HISTÓRIA À ERA CONTEMPORÂNEA E SUA EVOLU...
PRODUÇÃO E CONSUMO DE ENERGIA DA PRÉ-HISTÓRIA À ERA CONTEMPORÂNEA E SUA EVOLU...
Faga1939
 

Último (8)

Segurança Digital Pessoal e Boas Práticas
Segurança Digital Pessoal e Boas PráticasSegurança Digital Pessoal e Boas Práticas
Segurança Digital Pessoal e Boas Práticas
 
Logica de Progamacao - Aula (1) (1).pptx
Logica de Progamacao - Aula (1) (1).pptxLogica de Progamacao - Aula (1) (1).pptx
Logica de Progamacao - Aula (1) (1).pptx
 
Manual-de-Credenciamento ANATER 2023.pdf
Manual-de-Credenciamento ANATER 2023.pdfManual-de-Credenciamento ANATER 2023.pdf
Manual-de-Credenciamento ANATER 2023.pdf
 
História da Rádio- 1936-1970 século XIX .2.pptx
História da Rádio- 1936-1970 século XIX   .2.pptxHistória da Rádio- 1936-1970 século XIX   .2.pptx
História da Rádio- 1936-1970 século XIX .2.pptx
 
Certificado Jornada Python Da Hashtag.pdf
Certificado Jornada Python Da Hashtag.pdfCertificado Jornada Python Da Hashtag.pdf
Certificado Jornada Python Da Hashtag.pdf
 
TOO - TÉCNICAS DE ORIENTAÇÃO A OBJETOS aula 1.pdf
TOO - TÉCNICAS DE ORIENTAÇÃO A OBJETOS aula 1.pdfTOO - TÉCNICAS DE ORIENTAÇÃO A OBJETOS aula 1.pdf
TOO - TÉCNICAS DE ORIENTAÇÃO A OBJETOS aula 1.pdf
 
DESENVOLVIMENTO DE SOFTWARE I_aula1-2.pdf
DESENVOLVIMENTO DE SOFTWARE I_aula1-2.pdfDESENVOLVIMENTO DE SOFTWARE I_aula1-2.pdf
DESENVOLVIMENTO DE SOFTWARE I_aula1-2.pdf
 
PRODUÇÃO E CONSUMO DE ENERGIA DA PRÉ-HISTÓRIA À ERA CONTEMPORÂNEA E SUA EVOLU...
PRODUÇÃO E CONSUMO DE ENERGIA DA PRÉ-HISTÓRIA À ERA CONTEMPORÂNEA E SUA EVOLU...PRODUÇÃO E CONSUMO DE ENERGIA DA PRÉ-HISTÓRIA À ERA CONTEMPORÂNEA E SUA EVOLU...
PRODUÇÃO E CONSUMO DE ENERGIA DA PRÉ-HISTÓRIA À ERA CONTEMPORÂNEA E SUA EVOLU...
 

Entendento Arquitetura MVI + Flow

Notas do Editor

  1. 2 anos com MVI Experiencia do service App Interagir
  2. Even MVI is very powerful to write integration test this will be for next time Por mais que vamos ver escopo no código, nao eh o foco dessa palestra entrar no assunto
  3. Model/State immutable, like this we can have only on source of true
  4. Pretty much the same, it represents UI
  5. THIS IS NOT ANDROID INTENT In order to help us to better understand I will call intent as event
  6. Aqui podemos ver um versão mais base do MVI Muitas arquitetura MVVM chegam perto ou são implementadas dessa mesma maneira No exemplo dessa talk vamos ter alguns outros componentes para construir nossa arquitetura MVI Que sao o Action Creator e o Reducer, vou explicar sobre eles mais pra frente, mas ja guardem esse nome
  7. Essa eh a nossa aplicação Vamos desenvolver juntos a funcionalidade de decrementar Deixar mais claro ou rodar o app
  8. Trazendo mais uma visualização do MVI dessa vez matematicamente v(m(I())) eh uma função composta por outras funções Funçao equivalente, com multiplos inputs tem apenas um output Math might not be everyone’s cup of tea, but a mathematician doesn’t know what a bug is. Software Engineers do.
  9. Mau implementados podem te dar muita dor de cabeça Tratado com carinho sao as soluções de todos os seus problemas MVI faz isso muito bem
  10. Ficamos 3 horas para decidir oq nossa view model era responsável Agora lancei mais duas novas palavras ActionCreator e o Reducer e Guard
  11. View que ja sabemos = UI Model Separar O que eh o Model?
  12. Alguem consegue ver oq eh o model aqui? repository? Interface view? Loading/updateCounter/error?
  13. E aqui na minha view, quando, onde e como? Eu posso falar que chegou apenas 1 output igual a gente view na função no slide anterior?
  14. Esse eh o comportement do MVP, nao possui nenhum estado Por sua vez o MVP controla o estado da view, em relação a mostrar ou esconder algo.
  15. Mesmas perguntas aqui Onde esta o model?
  16. Cade o model?
  17. Diferente do presenter o viewmodel tem estado e por sua vez sempre que esse estado eh alterado ele notifica a view que esta observando esse estado
  18. Vamos pensar no model dessa maneira, um data class que contem todos os meus views states.
  19. De forma mais grafica seria mais ou menos isso Model contem oq vem da minha API e contem os estados que minha view vai ter
  20. Mutabilidade, onde diferentes lugares podem alterar o seu model/state Multiplos estados, nao somente estados da view, mas um estado da sua requisição por exemplo, estado do seu view model e estado da sua view que seria isEnable, isVisible entre outros. Por que devemos sincronizar? Evitar suposição do estado atual para enviar o proximo.
  21. Criando nosso model e colocando os states dentro do model a gente traz um pouco de imutabilidade, enviando cada vez um estado para nossa view. Loading Counter Error Todos vao através do render function da minha interface
  22. Que por sua vez, recebe em um soh lugar os estado. Parte ruim de colocar tudo em um data class eh que eu preciso colocar alguns items como opcional Porem a gente ve que recebemos em apenas um lugar, um output igual a função matemática que a gente view. Uma unica fonte da verdade de onde vai chegar o meu state.
  23. Mutable live data
  24. Apenas 1 uma fonte de vdd na minha view
  25. O que aconteceria se eu tivesse isso como output? Opcionais mas eu to recebendo :/
  26. Nesse exemplo que aconteceu comigo eu tive o seguinte fluxo Recebi uma notificação como pode ver que ta com o marcador Abri a tela e recebi um empty state E meu loading ficou infinito Aqui podemos ver dois problemas 1 - Multiplos estados 2 - Estados nao estao sincronizados, pq eu consigo enviar meus novos estados mas na vdd nao deveria, pois isso ira gerar um estado estranho na minha view. Ja viu isso acontecer com algum app que vc usa?
  27. Vantagens e desvantagens de usar um data class único
  28. Podemos ver que agora minha classe virou um state, onde o model esta dentro do content, o valor que vem do repositorio sera inserido ali dentro. Nao vejo desvantagens, se alguém ve me fala depois quero saber de vdd :)
  29. Agora na minha view eu nao preciso mais tratar opcional, pq cada classe tem o seu campo. Porem a parte de sincronização ainda nao foi solucionada, eh ai que entra o MVI.
  30. Nao corrige o problema de sincronização Nada tecnicamente Assumir que posso enviar um novo estado sem saber qual estado ja foi enviado Notification e depois um empty???
  31. Ta tudo certo ai galera? Deu pra entender o problema que ficou em aberto? Vc ja parou pra pensar que rolam outros estados alem do viewModel na sua aplicação? 1 - Estado da sua requisição 2 - Estado da view model que estamos mais acostumados 3 - Estado da view, que embora a gente pense que eh o estado do view model por exemplo o loading, na vdd o estado da view se refere a view por si mesmo, como isEnable, isVisible, core de texto o próprio texto e outros muito possíveis estados que a view pode ter. Compose vai melhorar muito isso.
  32. Pra melhor exemplificar essa sincronização de estados, vou explicar sobre maquina de estados
  33. Jamais parado em cima do acabado
  34. Muitos apps tem os estados, mas a gente nao tem ideia da maquina de estado Isso tem que estar visível todo o tempo, principalmente quando vc vai alterar o código
  35. Evento e acoes sao coisas diferentes Evento = Intent do usuario ou do app em fazer algo Acao = Seria o trigger para um novo estado Acoes que nao podem acontecer de jeito nenhum
  36. Evento + Acao + Estado
  37. O que acontece nessa transição para garantir que eu posso enviar um estado de loading? Action Creator Reducer Guard
  38. Esse e o proximo slide são muito importantes pra vc entender o restante Se vc ta mexendo no celular, deixa de lado um pouquinho e foca aqui
  39. Classes Action = (Event) -> Action Reducer = (CurrentState, Action) -> NewState Guard = Boolean
  40. toState eh uma cadeia que recebe um evento do usuário e devolve o novo estado, lembrem desse nome toState pois vamos ver essa cadeia inteira no código escrito com flow. Falar q entende que eh o primeiro contato, vamos ver muito mais exemplos.
  41. Deixar claro que intent=event Varias coisas acontecem
  42. Uma mensagem importante para mostrar para o usuário esta na tela, ele esta lendo, nao posso sobrepor com um conteúdo
  43. Vamos dizer que temos um event do usuário, uma intent como a gente viu. No final isso ira refletir em um novo estado.
  44. Essa parte de concatenar eh um ganho muito grande
  45. Problema similar MVI + Flow ajuda
  46. Vamos imaginar o seguinte cenário Na minha view eu tenho 2 tipos eventos que podem acontecer distintivamente em momentos separados Vamos dar nome aos bois
  47. Regra no 2 Nunca vai descobrir
  48. Desabilitar Travar a tela Encerra comunicação Loading tempo, 15s? Pessima experiencia Informar, Cancelar
  49. Substituir Usar para contar 5s botao desabilitado esperando resultado???
  50. Bonito mas nao funciona N tratar eventos
  51. Agora temos a mesma situação mas com eventos enfileirados O MVI vai me ajudar muito com isso, principalmente com o flow.
  52. Como falei no começo o propósito dessa palestra eh que vc entenda a arquitetura MVI e para isso utilizaremos flow para construir um fluxo unidirecional. Antes de ver o fluxo inteiro do MVI gostaria de granular em pequenas partes que existem, para assim melhor entender o contexto geral de MVI. Debugavel
  53. Process mesmo tipo
  54. Action creator Reducer Guard
  55. Producer - emission Intermediary - transformação Consumer - coleta o dado
  56. Controla simultaneidade com fluxos Flows são COLD
  57. O que vamos ver agora eh o MVI tratando esses dois caras
  58. The flow builder is executed within a coroutine. Thus, it benefits from the same asynchronous APIs, but some restrictions apply: Flows are sequential. As the producer is in a coroutine, when calling a suspend function, the producer suspends until the suspend function returns. In the example, the producer suspends until the fetchLatestNews network request completes. Only then is the result emitted to the stream. With the flow builder, the producer cannot emit values from a different CoroutineContext. Therefore, don't call emit in a different CoroutineContext by creating new coroutines or by using withContext blocks of code. You can use other flow builders such as callbackFlow in these cases.
  59. Eh um dos operadores terminais do flow tais como single, reduce, toList e launchIn
  60. Na minha opniao nao vejo flow contra livedata ou vice versa. Os dois trabalham muito bem juntos no que sabem fazer de melhor Existem algumas maneiras de coletar flow na view, porem existem algumas diferenças e nao vou entrar nesse assunto agora Pra mim converter flow para livedata na view e observar ficou muito bem atrelado ao view scope LD hold value Sao diferentes
  61. Vamos falar que a gente quer enviar 1 + n eventos Por exemplo, enviar o loading e o resultado da minha api
  62. Rever
  63. Rever
  64. Stream/Criaçao de uma cadeia, ajudando muito no momento de enfileirar eventos
  65. Livedata com os intermediarios do flow para transformação
  66. Igual o state flow Quantas vezes emitir Bom para eventos
  67. Bagunça Como ta ai pessoal? ActionCreator, Reducer, Guard??
  68. + MVI Cadeia Exemplo Meu projeto
  69. SharedFlow event Channel State flow toState
  70. Falar sobre o process que vem da view os eventos Btn click 1 flow merge
  71. Curaçao Event -> State Cadeia
  72. Todos os eventos recebidos da view vao passar aqui
  73. Vou chamar meu action (Event) -> Action que sera executada pela view Increase = Evento Action = Executing/Success/Error
  74. (currentState,Action) -> NewState
  75. Logando quando completar Convertendo de flow para stateflow Dando o scope do viewmodel para sobreviver a rotação Lazily para enviar somente quando alguém estiver coletando E inicial estado Guard ta dentro do meu reducer
  76. Me de algum feedback, algo que talvez nao esta tao claro para eu mostrar agora no código. Roteiro do live code 1- setOnClickListenerFlow 2- Criar o evento Decrease 3 - implementar o btnDecrease 4 - Action Creator, deixar o TODO para ver o erro, depois implementar. 5 - CounterState 6 - Reducer 7 - Guard(Explicar o assert, mostrar o guard dando erro e fazer o catch do erro no view model nos próximos estados) 8 - View Model(View model fica bem genérico, fácil implementação) 9 - State view model(falar que pode ser mais granulado, ter um cara para despachar minhas acoes, chamar de store e etc) mostrar o chain linha por linha 10 - Testes Unitarios(runblocking os caras vão querer me matar haha) 11 - Testar o app 11.1 - Rotacao(1 evento rotaciona depois mais 1 evento) 11.2 - Mudar de app, falar sobre o render state
  77. Eu espero muito que vc conseguiu entender um pouco de MVI e seus benefícios. Nao estou aqui para falar que MVI eh a melhor arquitetura e seu código eh ruim, existem diferentes necessidades para diferentes casos. Tbm existem outras implementações para MVI, outras nomenclaturas e etc, faça do jeito que for melhor para o seu projeto.
  78. Pelo Mundo Associate Android Developer