UI 架構模式 ——MVI#
MVC/MVVM/MV 的問題#
MVC/MVVM/MV 都將 View 和 Model 分離,Model/ViewModel/StatefulModel 中需要處理和保存 View 的狀態,因此當頁面交互和組件開發變得複雜時,難以保證整個應用的狀態一致性。
什麼是 MVI#
MVI 模式全稱 Model-View-Intent 模式。MVI 將處理邏輯分為三部分:Model、View 和 Intent。Model 負責處理數據和業務邏輯,View 負責渲染 UI 和用戶交互,Intent 則負責消息傳遞,將用戶輸入的動作、View 的事件、Model 的狀態變化等封裝成 Intent,將 Intent 發送給 Model,Model 處理後再發送給 View 進行渲染。這種方式保證了整個應用狀態的一致性,並能夠比較方便地處理複雜的 UI 狀態同步問題。
View(Model(Intent()))
MVI 與 MVC/MVVM/MV 有什麼不同#
與 MVC/MVVM/MV 相比,MVI 更加關注數據流與狀態管理,強調單向數據流和單一可信來源原則。MVC/MVVM/MV 都可以採用 MVI 中的數據流和狀態管理思想來進行改進,使得應用更加易於維護和擴展。因此,MVI 不是完全獨立於 MVC/MVVM/MV 的,而是一種基於它們的深度實踐和擴展。
MVI 的使用#
MVI 使用統一狀態解決 ui 狀態一致性問題,使用 Intent-Reducer-State 單向數據流解決狀態之間的複雜關係。
selector : (state)->state
render : (state)
[View]
package ViewModel {
[UiState]
[UiIntent]
[Reducer]
}
[UiState] -up-> [View] : observe(selector,render)
[View] -down-> [UiIntent] : dispatch(intent)
[UiIntent] -down-> [Reducer]
[Reducer] -up-> [UiState] : reduce(intent,state) -> state
MVI 和組合模式#
在 MVI 架構中,每個界面組件都擁有自己獨立的 State 和 Intent,這些 State 和 Intent 會通過組合的方式構成整個界面的 State 和 Intent。通過這種方式,我們可以更好地管理界面狀態和用戶行為,代碼組織更加清晰,可維護性更高,在開發大型應用時也能提高效率。
class Page
class View1
class View2
class View1State
class View2State
class PageState
Page *-left- View1
Page *-right- View2
PageState *-left- View1State
PageState *-right- View2State
View1 -down-> View1State
View2 -down-> View2State
data class View1Intent
data class View2Intent
data class PageIntent{
View1(val state:View1State):PageIntent
View2(val state:View2State):PageIntent
}
fun dispatch(intent:PageIntent){
when(intent){
is View1 -> dispatch(View1.sate)
is View2 -> dispatch(View2.sate)
}
}