關(guān)注個人簡介,技術(shù)不迷路~
從模型-視圖-視圖模型 (MVVM) 架構(gòu)遷移到模型-視圖-意圖 (MVI) 架構(gòu)似乎是一項艱巨的任務(wù)。但憑借更清晰的架構(gòu)和更可預(yù)測的應(yīng)用程序行為的好處,這是一次非常值得付出努力的轉(zhuǎn)變。
在本文中,我們將探討 MVVM 和 MVI 之間的差異,并提供有關(guān)如何遷移到 MVI 的指導(dǎo)。
MVVM 與 MVI
MVVM 架構(gòu)是移動應(yīng)用程序開發(fā)中廣泛使用的模式。它將用戶界面(View)與數(shù)據(jù)和邏輯(ViewModel)分開,并允許兩個組件之間進(jìn)行數(shù)據(jù)綁定。ViewModel 負(fù)責(zé)為 View 準(zhǔn)備數(shù)據(jù)并處理用戶輸入。
另一方面,MVI 架構(gòu)是近年來流行的一種較新的模式。它還將視圖和數(shù)據(jù)分開,但添加了一個稱為意圖的新層,該層負(fù)責(zé)以結(jié)構(gòu)化且可預(yù)測的方式表示用戶操作。Intent 被傳遞給模型,模型產(chǎn)生一個新的狀態(tài),然后顯示在視圖中。
兩種架構(gòu)之間的主要區(qū)別在于,在 MVVM 中,ViewModel 負(fù)責(zé)用戶操作和更新視圖狀態(tài)。在 MVI 中,意圖是一個代表用戶操作的獨(dú)立層,可以更輕松地推斷應(yīng)用程序行為并處理邊緣情況。
為什么選擇 MVI?
1.更好的關(guān)注點分離: 使用MVI,Intent層負(fù)責(zé)用戶操作,Model層負(fù)責(zé)狀態(tài)管理,View層負(fù)責(zé)狀態(tài)渲染。這種分離使得推斷應(yīng)用程序行為以及對應(yīng)用程序進(jìn)行更改變得更加容易,而不會影響架構(gòu)的其他部分。
2. 更可預(yù)測的應(yīng)用程序行為: 使用 MVI,應(yīng)用程序的狀態(tài)始終由單個數(shù)據(jù)對象表示,這使得更容易推理和預(yù)測應(yīng)用程序的行為。這種可預(yù)測性可以減少錯誤并提供更好的用戶體驗。
3. 提高可測試性: MVI 使編寫單元測試變得更加容易,因為每一層都可以獨(dú)立測試。通過架構(gòu)的可預(yù)測數(shù)據(jù)流使得編寫涵蓋所有可能狀態(tài)和邊緣情況的測試變得更加容易。
如何從 MVVM 遷移到 MVI?
從 MVVM 遷移到 MVI 似乎是一項艱巨的任務(wù),但重要的是要記住這是一個漸進(jìn)的過程。以下是一些需要考慮的步驟:
- 了解MVI架構(gòu): 在進(jìn)行切換之前,請確保您了解MVI的關(guān)鍵概念,包括Intent層和單向數(shù)據(jù)流。
- 識別組件: 仔細(xì)查看現(xiàn)有的 MVVM 代碼并識別需要更改的組件。這包括 ViewModel、View 以及任何數(shù)據(jù)模型或存儲庫。
- 創(chuàng)建 Intent 層:將 Intent 層添加到您的應(yīng)用程序中,該層以結(jié)構(gòu)化且可預(yù)測的方式表示用戶操作。該層應(yīng)該與 ViewModel 和 Model 分開。
- 更新 ViewModel: 修改您的 ViewModel 以接受 Intent 并將其傳遞給模型。ViewModel 不應(yīng)再負(fù)責(zé)更新 View 的狀態(tài)。
- 更新模型: 修改模型以根據(jù)意圖和當(dāng)前狀態(tài)生成新狀態(tài)。模型不應(yīng)再負(fù)責(zé)處理用戶輸入。
- 更新視圖: 修改視圖以呈現(xiàn)模型提供的狀態(tài)。視圖不應(yīng)再負(fù)責(zé)獲取數(shù)據(jù)或更新狀態(tài)。
- *****為架構(gòu)的每一層* **編寫單元測試,以確保數(shù)據(jù)流可預(yù)測,并覆蓋所有可能的狀態(tài)和邊緣情況。****
從 MVVM 遷移到 MVI 的實施主要步驟
第 1 步:創(chuàng)建 Intent 類
sealed class MyIntent {
object LoadData : MyIntent()
data class UpdateData(val newData: Data) : MyIntent()
object DeleteData : MyIntent()
}
第2步:修改ViewModel
修改您的 ViewModel 以接受意圖并將其傳遞給模型。ViewModel 不應(yīng)再負(fù)責(zé)更新 View 的狀態(tài)。
class MyViewModel ( private val myModel: MyModel) : ViewModel() {
private val _state = MutableLiveData<MyState>()
val state: LiveData<MyState> = _state
fun processIntent (intent: MyIntent ) {
val newState = myModel.processIntent(intent, _state.value)
_state.postValue(newState)
}
}
第三步:創(chuàng)建State類
創(chuàng)建一個表示應(yīng)用程序當(dāng)前狀態(tài)的類,例如:
class MyModel(private val myRepository: MyRepository) {
fun processIntent(intent: MyIntent, currentState: MyState?): MyState {
return when (intent) {
is MyIntent.LoadData -> {
// Load data from repository
myRepository.getData()
.map { data -> currentState?.copy(data = data) ?: MyState(data = data) }
.onStart { emit(currentState?.copy(isLoading = true) ?: MyState(isLoading = true)) }
.onErrorReturn { throwable ->
currentState?.copy(isLoading = false, error = throwable)
?: MyState(isLoading = false, error = throwable)
}
}
is MyIntent.UpdateData -> {
// Update data in repository
myRepository.updateData(intent.newData)
currentState?.copy(data = intent.newData) ?: MyState(data = intent.newData)
}
is MyIntent.DeleteData -> {
// Delete data from repository
myRepository.deleteData()
MyState()
}
}
}
}
第5步:修改視圖
修改視圖以呈現(xiàn)模型提供的狀態(tài)。視圖不應(yīng)再負(fù)責(zé)獲取數(shù)據(jù)或更新狀態(tài)。
class MyActivity : AppCompatActivity() {
private val viewModel: MyViewModel by viewModels()
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_my)
viewModel.state.observe(this, Observer { state ->
// Render state in UI
when {
state.isLoading -> showLoading()
state.error != null -> showError(state.error)
state.data != null -> showData(state.data)
}
})
}
private fun showLoading() {
// Show loading spinner or progress bar
}
private fun showError(error: Throwable) {
// Show error message
}
private fun showData(data: Data) {
// Show data in UI
}
}
結(jié)論
總之,從 MVVM 遷移到 MVI 可以為您的 Android 應(yīng)用帶來多項好處。通過采用 MVI 架構(gòu),您可以創(chuàng)建更具反應(yīng)性、可預(yù)測性和可測試性的應(yīng)用程序,同時減少層之間的耦合并提高代碼庫的整體可維護(hù)性。
MVI 允許您將用戶交互建模為意圖,根據(jù)這些意圖更新應(yīng)用程序的狀態(tài),然后在 UI 中呈現(xiàn)該狀態(tài)。這使得您可以更輕松地推斷應(yīng)用程序中的數(shù)據(jù)流,并更改代碼,而不會引入意外的副作用。此外,MVI 有助于避免 MVVM 中的常見問題,例如“回調(diào)地獄”和“狀態(tài)爆炸”。
當(dāng)然,從 MVVM 遷移到 MVI 存在一些挑戰(zhàn),例如需要重構(gòu)現(xiàn)有代碼以及學(xué)習(xí)新的概念和模式。然而,通過仔細(xì)的規(guī)劃、清晰的文檔和徹底的測試,MVI 的好處可以遠(yuǎn)遠(yuǎn)超過成本。通過采用像 MVI 這樣的反應(yīng)式和可預(yù)測的架構(gòu),您可以創(chuàng)建更可靠、可擴(kuò)展和可維護(hù)的 Android 應(yīng)用程序,以滿足用戶和利益相關(guān)者的需求。