This article has participated in the “Digitalstar Project” and won a creative gift package to challenge the creative incentive money.
preface
Android development to today has been quite mature, a variety of architecture we are also familiar with, such as MVC,MVP,MVVM, etc., among which MVVM is officially recommended, become prominent in Android development. However, there is no silver bullet in software development, MVVM architecture is not perfect, there will be some inconvenient in the use process, and MVI can be a good solution to part of the PAIN points of MVVM. This article mainly includes the following contents
MVC
.MVP
.MVVM
And so on classical architectureMVI
What exactly is architecture?MVI
Architecture of actual combat
It should be pointed out that the title says that MVI architecture is an advanced version of MVVM, which means that MVI is very similar to MVVM and has made some improvements on its basis. It does not mean that MVI architecture is necessarily more suitable for your project than MVVM. Students can choose the architecture suitable for the project scenario after analyzing and comparing various architectures
Introduction to classic Architecture
MVC
Architecture is introduced
MVC
It’s an ancientAndroid
Develop the architecture along withMVP
withMVVM
The popularity of… has gradually faded from the historical stage. We make a simple introduction here, and its architecture is shown as follows:
MVC
The architecture is divided into the following parts
- The view layer (
View
) : correspond toxml
Layout files andjava
Code dynamicview
Part of the - Control layer (
Controller
) : Mainly responsible for business logic, inandroid
byActivity
Bear, at the same time becauseXML
The view is too weak, soActivity
Taking on too many functions to display the view and add control logic. - The model layer (
Model
) : Mainly responsible for network request, database processing,I/O
That is, the data source of the page
Due to theandroid
In thexml
The layout is too weak for functionality,Activity
In fact in charge ofView
Layer andController
Layer both work, so inandroid
In themvc
It’s more like this:
soMVC
Architecture inandroid
The main problems on the platform are as follows:
Activity
Also responsible forView
withController
Layer of work that violates the principle of single responsibilityModel
Layer andView
There is coupling and interdependence between layers, which violates the principle of minimum knowledge
MVP
Architecture is introduced
Due to theMVC
Architecture inAndroid
Some of the flaws in the platform,MVP
The resulting architecture is shown below
MVP
The architecture is divided into the following parts
View
Layer: corresponds toActivity
withXML
Is only responsible for displayUI
, only withPresenter
Layer interaction, andModel
Layers are not coupledPresenter
Layer: handles the business logic and calls back through the interfaceView
layerModel
Layer: mainly responsible for network requests, database processing and other operations, there is no change in this
As we can see, MVP solves two problems with MVC, namely the Activity taking on two layers of responsibility and coupling the View layer to the Model layer
But the MVP structure has its own problems
Presenter
Layers interact with each other through interfacesView
Communication actually holds upView
A reference to the- But as the business logic grows, a page can become so complex that it can cause
View
The interface will be huge.
MVVM
Architecture is introduced
MVVM
Model willPresenter
renamedViewModel
, basically withMVP
The pattern is exactly the same.
The only difference is that it uses two-way data binding (data-binding
) :View
Changes are automatically reflected inViewModel
And vice versa
MVVM
The architecture diagram is as follows:
It can be seen thatMVVM
withMVP
The main difference is that you don’t have to actively refreshUI
As long asModel
When the data changes, it automatically shows upUI
On. In other words,MVVM
It’s more automatedMVP
.
MVVM
The bidirectional data binding is mainly throughDataBinding
Implementation, but I believe there are many people like me, is not like to useDataBinding
So the architecture becomes the following
View
To observe theViewModle
The data changes and updates itself. This is actually a single data source and not a two-way data binding, so in factMVVM
“Is a feature I don’t actually useView
By calling theViewModel
Provides methods to come withViewMdoel
interaction
summary
MVC
The main problem with architecture is thatActivity
To undertake theView
withController
Two layers of responsibility, at the same timeView
Layer andModel
There is coupling in layersMVP
The introduction ofPresenter
Layer to solve theMVC
Two problems with architecture,View
Only withPresenter
Layer interaction, business logic inPresenter
layerMVP
The problem is that as business logic increases,View
The interface will be huge,MVVM
The architecture solves this problem with two-way data bindingMVVM
withMVP
The main difference is that you don’t have to actively refreshUI
As long asModel
When the data changes, it automatically shows upUI
On. In other words,MVVM
It’s more automatedMVP
.MVVM
The bidirectional data binding is mainly throughDataBinding
Yes, but a lot of people (like me) don’t like to use itDataBinding
, butView
throughLiveData
Such as watchViewModle
This is a single data source rather than a two-way data binding
MVI
What exactly is architecture?
MVVM
What are the weaknesses of the architecture?
In order to ensure the one-way flow of data, LiveData must be converted to IMmutable when exposed. This requires a lot of template code and is easy to forget, as shown in the following
class TestViewModel : ViewModel() {
// To ensure that exposed LiveData is immutable, adding a state requires adding two LiveData variables
private val _pageState: MutableLiveData<PageState> = MutableLiveData()
val pageState: LiveData<PageState> = _pageState
private val _state1: MutableLiveData<String> = MutableLiveData()
val state1: LiveData<String> = _state1
private val _state2: MutableLiveData<String> = MutableLiveData()
val state2: LiveData<String> = _state2
/ /...
}
Copy the code
As shown above, if the page logic is complex, the ViewModel will have many global variable LiveData, and each LiveData must be defined twice, one mutable and one immutable. This is actually the hardest part of writing complex pages using the MVVM architecture. Second is the View layer by calling the method of the ViewModel layer to interact, View layer and ViewModel interaction is more scattered, not systematic
To summarize, in my use, the MVVM architecture has the following major shortcomings
- To ensure exposure to the outside world
LiveData
Is immutable, requires a lot of template code to add and is easy to forget View
Layer andViewModel
Layer interactions are scattered and disorganized
MVI
What is architecture?
MVI
与 MVVM
It is similar in that it borrows from the ideas of the front-end framework, with more emphasis on one-way flow of data and unique data sources, as shown in the architecture diagram below
It is mainly divided into the following parts
Model
And:MVVM
In theModel
The difference is,MVI
theModel
Mainly refers toUI
State (State
). Page loading status, control location, etcUI
stateView
: with the otherMVX
In theView
Consistent, maybe oneActivity
Or anyUI
Carrying unit.MVI
In theView
By subscribing toIntent
Changes to implement interface refresh (note: this is notActivity
theIntent
)Intent
: thisIntent
notActivity
theIntent
Any operation of the user is wrapped asIntent
The coma toModel
Layer to make data requests
Unidirectional data flow
MVI emphasizes the one-way flow of data, which is mainly divided into the following steps:
- User operation to
Intent
Form notice ofModel
Model
Based on theIntent
updateState
View
To receiveState
Changes refresh the UI.
Data always flows in one direction in a circular structure, not the other:
The above briefly introduced the MVI architecture, let’s see how to use the MVI architecture in detail
MVI
Architecture of actual combat
Overall architecture diagram
We use theViewModel
To carryMVI
theModel
Layer, the overall structure also withMVVM
Similar, but the main difference isModel
withView
Part of the layer interaction
Model
layerUI
State, and exposedViewState
forView
To subscribe to,ViewState
Is adata class
Contains all page statesView
Layer throughAction
updateViewState
To replaceMVVM
By calling theViewModel
How methods interact
MVI
introduces
addViewState
withViewEvent
ViewState holds all the states of the page, and ViewEvent is a one-time event, such as Toast, as shown below
data class MainViewState(val fetchStatus: FetchStatus, val newsList: List<NewsItem>)
sealed class MainViewEvent {
data class ShowSnackbar(val message: String) : MainViewEvent()
data class ShowToast(val message: String) : MainViewEvent()
}
Copy the code
- We are here
ViewState
Only two are defined, one is the request state and one is the page data ViewEvent
Also very simple, a simple sealing class, displayToast
withSnackbar
ViewState
update
class MainViewModel : ViewModel() {
private val _viewStates: MutableLiveData<MainViewState> = MutableLiveData()
val viewStates = _viewStates.asLiveData()
private val _viewEvents: SingleLiveEvent<MainViewEvent> = SingleLiveEvent()
val viewEvents = _viewEvents.asLiveData()
init {
emit(MainViewState(fetchStatus = FetchStatus.NotFetched, newsList = emptyList()))
}
private fun fabClicked(a) {
count++
emit(MainViewEvent.ShowToast(message = "Fab clicked count $count"))}private fun emit(state: MainViewState?). {
_viewStates.value = state
}
private fun emit(event: MainViewEvent?). {
_viewEvents.value = event
}
}
Copy the code
As shown above
- We just need to define
ViewState
withViewEvent
twoState
, and the subsequent increase of state indata class
You don’t need to write template code ViewEvents
It’s a one-time passSingleLiveEvent
Implementation, of course you can use itChannel
When to achieve- When the status is updated, pass
emit
To update the status
View
Listening to theViewState
private fun initViewModel(a) {
viewModel.viewStates.observe(this) {
renderViewState(it)
}
viewModel.viewEvents.observe(this) {
renderViewEvent(it)
}
}
Copy the code
As you can see above, MVI uses ViewState to centrally manage State. You only need to subscribe to a ViewState to get all the State of a page, which reduces a lot of template code compared to MVVM.
View
throughAction
updateState
class MainActivity : AppCompatActivity() {
private fun initView(a) {
fabStar.setOnClickListener {
viewModel.dispatch(MainViewAction.FabClicked)
}
}
}
class MainViewModel : ViewModel() {
fun dispatch(action: MainViewAction) =
reduce(viewStates.value, action)
private fun reduce(state: MainViewState? , viewAction:MainViewAction) {
when (viewAction) {
is MainViewAction.NewsItemClicked -> newsItemClicked(viewAction.newsItem)
MainViewAction.FabClicked -> fabClicked()
MainViewAction.OnSwipeRefresh -> fetchNews(state)
MainViewAction.FetchNews -> fetchNews(state)
}
}
}
Copy the code
As shown above, the View interacts with the ViewModel through Action and communicates through Action, which is conducive to further decoupling between View and ViewModel. Meanwhile, all calls are summarized in the form of Action, which is also conducive to centralized analysis and monitoring of behavior
conclusion
This article mainly introduces MVC,MVP,MVVM and MVI architectures. Currently,MVVM is the official recommended architecture, but there are still several pain points
MVVM
withMVP
The main difference is two-way data binding, which many people (like me) don’t like to useDataBindg
“Is not actually usedMVVM
Bidirectional binding features, but a single data source- When pages are complex, there is a lot to define
State
, and need to define both mutable and immutable, the state will double the rate of expansion, template code is more and easier to forget View
withViewModel
throughViewModel
Exposed method interactions are messy and difficult to maintain
MVI can better solve the above pain points, and it has the following advantages
- Emphasize the one-way flow of data, making it easy to track and trace state changes
- use
ViewState
rightState
Centralized management, only need to subscribe to oneViewState
To get all the state of the page, relativeMVVM
Much less template code ViewModel
throughViewState
withAction
Communicate by browsingViewState
和Aciton
The definition is clearViewModel
Can be used directly as an interface document.
Of course, MVI also has some disadvantages, such as
- All operations will eventually be converted to
State
, so when complex pagesState
Easy to swell state
Is constant, so every timestate
Whenever an update is required, a new object is created to replace the old object, which incurs some memory overhead
There is no silver bullet in software development. All architectures are not perfect and have their own scenarios that readers can choose to use according to their own needs. However, based on the above analysis and introduction, I believe that using MVI architecture instead of MVVM without DataBinding is a better choice
Sample
code
Github.com/shenzhen201…
The resources
Android BASED MVI architecture: How to choose from bidirectional binding to one-way data flow Jetpack Compose architecture? MVX Best Architecture For Android: MVI + LiveData + ViewModel = ❤️