前言
目前安卓開發一般都是用的mvvm模式,Jetpack的ViewModel是必不可少的一部分,而vm的生命周期要比Activity和Fragment長的,所以其一般不推薦其直接持有A或F,因為可能會造成記憶體泄漏的問題,但是不傳入,Context的獲取和顯示網路加載彈窗又成了問題.
正文
首先解決顯示網路加載彈窗的問題,其有兩種方案:
1.使用MutableLiveData
首先我們在BaseViewModel中加入彈窗的MutableLiveData
val dialogShow = MutableLiveData(false)
然后我們可以在A或F的onCreate中獲取vm的時候注冊dialogShow的變化監聽
val vm = ViewModelProvider(this).get(BaseViewModel::class.java)
vm.dialogShow.observe(this) { isShow ->
if (isShow) showWaitDialog() else dismissWaitDialog()
}
但是這樣寫太麻煩了,可以使用Kotlin的代理來簡單實作,這樣不僅宣告的更方便,且自動注冊了觀察者
inline fun <reified VM : BaseViewModel> BaseActivity.baseViewModel() = lazy {
val vm = ViewModelProvider(this).get(VM::class.java)
vm.dialogShow.observe(this) { isShow ->
if (isShow) showWaitDialog() else dismissWaitDialog()
}
vm
}
//Activity中
val vm by baseViewModel<BaseViewModel>()
這樣的有點很明顯,vm完全不用持有A或F,但缺點是無法拿到Context
2.將BaseActivity或BaseFragment傳入vm
就像AndroidViewModel一樣,將A傳入vm,但有的小伙伴可能會問了,那記憶體泄漏了怎么辦?辦法很簡單,等下次重建回來的時候替換掉已經銷毀的A即可,實作方式如下
open class BaseViewModel(
var baseActivity: BaseActivity//內部用于彈窗等的參考
) : ViewModel(){
fun getContext() = baseActivity
fun showWaitDialog(s: String?) = baseActivity.showWaitDialog(s)
fun dismissWaitDialog() = baseActivity.dismissWaitDialog()
}
//快捷獲取BaseViewModel
inline fun <reified VM : BaseViewModel> BaseActivity.baseViewModel(
factory: ViewModelProvider.Factory? = null
) = lazy {
val vm = ViewModelProvider(
this,
factory ?: BaseViewModelFactory(this@baseViewModel)
).get(VM::class.java)
vm.baseActivity = this
vm
}
class BaseViewModelFactory(private val baseActivity: BaseActivity) : ViewModelProvider.Factory {
override fun <T : ViewModel?> create(modelClass: Class<T>): T {
return modelClass.getConstructor(BaseActivity::class.java).newInstance(baseActivity)
}
}
//Activity中
val vm by baseViewModel<BaseViewModel>()
這樣在A中第一次使用vm的時候就會把baseActivity替換為自身,也就不存在記憶體泄漏的問題了
這樣就可以愉快的在vm中使用網路加載彈窗和獲取Context了
轉載請註明出處,本文鏈接:https://www.uj5u.com/yidong/291340.html
標籤:其他
