相關(guān)知識(shí)請(qǐng)參考:
【Android】mvvm架構(gòu)模式知識(shí)匯總 - 簡(jiǎn)書(shū)
demo地址
GitHub - askskysun/ImproveMvvmDemo
ImproveMvvmDemo: 封裝好的MvvmDemo,可以直接在項(xiàng)目中使用
分工
View
Activity處理UI交互相關(guān);
使用注意:
1、需要判斷的UI處理邏輯放在Activity,不要把顯示邏輯放在xml;
2、詳細(xì)DataBinding規(guī)范參考:
DataBinding實(shí)用指南 - 簡(jiǎn)書(shū)
點(diǎn)擊事件處理
在activity中設(shè)置一個(gè)接口,點(diǎn)擊事件統(tǒng)一在接口處理,通過(guò)view的id辨別點(diǎn)擊按鈕,因?yàn)辄c(diǎn)擊是用戶(hù)的操作,屬于UI層面的,統(tǒng)一在activity。
/**
* <pre>
* 點(diǎn)擊事件,使用自定義接口,在activity中統(tǒng)一調(diào)用
* </pre>
*/
public interface OnClickPresenter extends View.OnClickListener{
@Override
void onClick(View v);
}
Activity中
//點(diǎn)擊事件的處理
binding.setPresenter(this);
@Override
public void onClick(View v) {
switch (v.getId()) {
case R.id.click1_tv:
fanYiViewModel.getTranslateData();
break;
case R.id.click2_tv:
Toast.makeText(MVVMActivity.this, "點(diǎn)擊了2", Toast.LENGTH_SHORT).show();
break;
}
}
ViewModel
用于保存數(shù)據(jù),和數(shù)據(jù)交互邏輯;
顯示數(shù)據(jù)通過(guò)LiveData傳給Activity;數(shù)據(jù)處理邏輯、耗時(shí)操作交給Model;
使用注意:
1、記住絕對(duì)不可以直接去創(chuàng)建ViewModel實(shí)例,一定要通過(guò)ViewModelProvider(ViewModelStoreOwner)構(gòu)造函數(shù)來(lái)獲取。因?yàn)槊看涡D(zhuǎn)屏幕都會(huì)重新調(diào)用onCreate()方法,如果每次都創(chuàng)建新的實(shí)例的話(huà)就無(wú)法保存數(shù)據(jù)了;
2、由于Model會(huì)有耗時(shí)操作,但ViewModel隨時(shí)需要回收,為了防止內(nèi)存泄漏,調(diào)用Model方法時(shí)不要使用匿名內(nèi)部類(lèi)做回調(diào)或者直接把ViewModel傳給Model。使用一個(gè)自定義的接口傳給Model,Model用弱引用持有,這個(gè)可在基類(lèi)處理;
3、初始化可變數(shù)據(jù)放在ViewModel構(gòu)造器中;不可改變的數(shù)據(jù)在Activity處理,或者xml中寫(xiě)默認(rèn)值;
Model
數(shù)據(jù)處理,網(wǎng)絡(luò)請(qǐng)求、資源請(qǐng)求等耗時(shí)操作、異步操作;
需要處理的問(wèn)題
ViewModel與Model內(nèi)存泄漏問(wèn)題
由于Model會(huì)有耗時(shí)操作,生命周期可能比ViewModel長(zhǎng),所以在兩者交互時(shí)存在內(nèi)存泄漏的問(wèn)題;
在此我們可以用定義回調(diào)接口,從ViewModel傳給Model,在Model中弱引用持有,Model進(jìn)行回調(diào)時(shí)注意判空。這些我們使用泛型寫(xiě)在基類(lèi)里面。
1、Model中持有接口;
public abstract class BaseModel<I> {
/**
* 回調(diào)給ViewModel的接口
*/
protected WeakReference<I> iCallBackWeakRef;
public BaseModel(I iCallBack) {
iCallBackWeakRef = new WeakReference<>(iCallBack);
}
2、ViewModel必然持有Model,我們寫(xiě)在基類(lèi);
public abstract class BaseViewModel<M extends BaseModel> extends ViewModel {
protected M model;
public BaseViewModel() {
model = createModel();
}
protected abstract M createMory();
}
@Override
protected void onCleared() {
super.onCleared();
if (model != null) {
model.destory();
}
}
}
3、ViewModel把接口傳給Model;
public class TranslateViewModel extends BaseViewModel<TranslateModel> implements OnTranslateCallBack {
@Override
protected TranslateModel createModel() {
return new TranslateModel(this);
}