当前位置:网站首页>Analysis of Mvi Architecture
Analysis of Mvi Architecture
2022-08-05 05:06:00 【slow cavalry】
- This article is simple to useKotlin + 协程 + flow + channelWrite a fake login request案例(dev_20220804_mvi分支),Learn from this caseMvi架构.
- 在了解Mvi之前,建议先了解一下Mvvm,可以参考Mvc、Mvp和Mvvm
一.代码环节
- Just understanding concepts first can feel abstract,We analyze the logic of the code and the class combination corresponding to the codeMviconcept together,会清晰很多;
- The case contains a total of4个类,MainActivity、DemoViewModel、DemoIntent、DemoUiState,先贴上;
1.1.MainActivity
import android.os.Bundle
import android.view.View
import android.widget.TextView
import androidx.activity.viewModels
import androidx.appcompat.app.AppCompatActivity
import androidx.lifecycle.lifecycleScope
import kotlinx.coroutines.launch
class MainActivity : AppCompatActivity() {
private lateinit var textView: TextView
private val mDemoViewModel: DemoViewModel by viewModels()
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
textView = findViewById(R.id.textView)
lifecycleScope.launch {
//3.ViewLayer settings monitor(VMThe layer will actively trigger the callback after executing the corresponding logic according to the intent)
mDemoViewModel.mUiState.collect {
uiState ->
when (uiState) {
is DemoUiState.loginSuccess -> {
textView.setText(uiState.success)
}
is DemoUiState.loginFail -> {
textView.setText("登录失败")
}
is DemoUiState.beforeLogin -> {
textView.setText(uiState.bengin)
}
}
}
}
}
//1.Click the button to simulate a network request
fun login(view: View) {
lifecycleScope.launch {
//1.1.Pass the intent to ViewModel层
mDemoViewModel.mChannel.send(DemoIntent.LoginIntent)
}
}
override fun onDestroy() {
super.onDestroy()
//Channel是一种协程资源['热'流],Communicate across different coroutines
//If you don't close it after use,会造成不必要的浪费
mDemoViewModel.mChannel.close()
}
}
1.2.DemoViewModel
import androidx.lifecycle.ViewModel
import androidx.lifecycle.viewModelScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.channels.Channel
import kotlinx.coroutines.channels.consumeEach
import kotlinx.coroutines.flow.*
import kotlinx.coroutines.launch
/** * 意图类 * The intent class can be written in the correspondingViewModel类中,No need to go out separately * 好处:Avoid too fine particle size,thereby increasing the complexity of the project */
sealed class DemoIntent {
//The number of intents is added according to actual needs
object LoginIntent : DemoIntent()
}
class DemoViewModel : ViewModel() {
val mChannel = Channel<DemoIntent>()
private val mDemoUiState = MutableStateFlow<DemoUiState>(DemoUiState.beforeLogin("准备登录"))
//使用flow来监听
val mUiState: StateFlow<DemoUiState> = mDemoUiState
init {
handleIntentInfo()
}
private fun handleIntentInfo() {
viewModelScope.launch {
mChannel.consumeEach{
//consumeEach:channel(管道)Read the data recommendation scheme[直接使用receive是很容易出问题的]
//2.Receive the intent transmitted by the user
when(it){
//Why go through an intent here?rather than communication,The purpose is to facilitate management,Views are forV层跟VMLayers are better decoupled and code extensions
is DemoIntent.LoginIntent -> getLoginData()
}
}
}
}
private fun getLoginData() {
viewModelScope.launch {
requestLogin.flowOn(Dispatchers.Default)
.catch {
exception ->
mDemoUiState.value = DemoUiState.loginFail(exception)
}.collect {
loginInfo ->
mDemoUiState.value = DemoUiState.loginSuccess(loginInfo)
}
}
}
private val requestLogin: Flow<String> = flow {
val loginInfo = "登录成功" //Simulate a request to log in to the interface
emit(loginInfo)
}
}
1.3.DemoUiState
sealed class DemoUiState {
//为了降低复杂度,The parameters of the method are written(The parameters inside the brackets in the actual project are recommended to be encapsulated into generics)
data class beforeLogin(var bengin: String):DemoUiState()
data class loginSuccess(var success: String):DemoUiState()
data class loginFail(var exception: Throwable):DemoUiState()
}
- Next, we combine concepts and code to understandMvi
二.Mvi
2.1.站在AndroidThe developer's point of view is simple to understandMvi
- Suppose the user is operating oursApp,To perform a login operation,Then the code level will encapsulate the user's login operation with an intent(对应Mvi的i),Then pass this intent to ViewModel(M层的一部分),然后ViewModelAfter executing the corresponding logic,It will be notified by callbackView层(实现方式有多种,常用的就是Livedata,used in the caseFlow);
- 上面的场景,User action fromV层开始,The final feedback is also thereView层,数据的流向是单向的;
2.2.Mvi和Mvvm的区别
- 多了一个i(corresponding to the caseDemoIntent 类)and one lessdatabinding,Others feel no difference(至于DemoUiState 类,也可以在MvvmThere are also corresponding packages in );
2.3.Compare the code logic
- 从MainActivity的login方法开始,User performs login,Will go through the pipeline of the coroutine(A resource for coroutines,不是本文的重点,了解即可)传递一个DemoIntent.LoginIntent参数,其中DemoIntentA class is an intent class,LoginIntentis a specific intent,As for needDemoIntentHow many intents are defined in the context is determined by specific needs.Wrap the need for login into an intent and pass it to ViewModel层,ViewModel层接收了,对应在DemoViewModel类的handleIntentInfo方法中处理ViewThe intent passed by the layer,We only need to analyze the methodWhen语句即可,判断itWhich one corresponds toDemoIntentThe intent to decide the execution logic,当是DemoIntent.LoginIntentperform login(伪)网络请求()调用到getLoginData方法,Modify after requesting the interfacemDemoUiState.value的值,从而触发MainActivity类中的mDemoViewModel.mUiState设置的监听,然后ViewLayers execute different logic based on different conditions;
三.总结
- This article describes from specific codeMvi不同于Mvvm的点,Mvi的MLayers can correspondMvvm的VM层和M层的结合,Contains both intent and UITwo parts of the state change.The use level is simpler,但是个人觉得Mvi的M层于Mvvmis a bit bloated,And this bloated point everyone can learnMvvmThe advantages ofMviMake flexible changes.
- 关于Mvi的学习,Personally recommend articles-MVVM 进阶版:MVI 架构了解一下~
边栏推荐
猜你喜欢
Day019 方法重写与相关类的介绍
mutillidae download and installation
upload上传图片到腾讯云,如何上传图片
Homework 8.4 Interprocess Communication Pipes and Signals
u-boot debugging and positioning means
Day019 Method overriding and introduction of related classes
Flutter 父子组件如何都能收到点击事件
Visibility of multi-column attribute column elements: display, visibility, opacity, vertical alignment: vertical-align, z-index The larger it is, the more it will be displayed on the upper layer
Analyses the mainstream across technology solutions
小程序_动态设置tabBar主题皮肤
随机推荐
Flutter学习三-Flutter基本结构和原理
Flutter 父子组件如何都能收到点击事件
How to identify false evidence and evidence?
结构光三维重建(二)线结构光三维重建
入口点注入
MySQL中控制导出文件后变为了\N有什么解决方案吗?
小程序_动态设置tabBar主题皮肤
Flutter真机运行及模拟器运行
u-boot调试定位手段
【无标题】
After controlling the export file in MySQL, it becomes \N. Is there any solution?
WPF中DataContext作用
Why did you start preparing for the soft exam just after the PMP exam?
Judgment statement _switch and case
uva1325
how to measure distance from point to face in creo
说说数据治理中常见的20个问题
Redis - 13、开发规范
Feature preprocessing
Excel画图