相关知识请参考:
demo地址
GitHub - askskysun/ImproveMvvmDemo
ImproveMvvmDemo: 封装好的MvvmDemo,可以直接在项目中使用
分工
View
Activity处理UI交互相关;
使用注意:
1、需要判断的UI处理逻辑放在Activity,不要把显示逻辑放在xml;
2、详细DataBinding规范参考:
点击事件处理
在activity中设置一个接口,点击事件统一在接口处理,通过view的id辨别点击按钮,因为点击是用户的操作,属于UI层面的,统一在activity。
/**
* <pre>
* 点击事件,使用自定义接口,在activity中统一调用
* </pre>
*/
public interface OnClickPresenter extends View.OnClickListener{
@Override
void onClick(View v);
}
Activity中
//点击事件的处理
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, "点击了2", Toast.LENGTH_SHORT).show();
break;
}
}
ViewModel
用于保存数据,和数据交互逻辑;
显示数据通过LiveData传给Activity;数据处理逻辑、耗时操作交给Model;
使用注意:
1、记住绝对不可以直接去创建ViewModel实例,一定要通过ViewModelProvider(ViewModelStoreOwner)构造函数来获取。因为每次旋转屏幕都会重新调用onCreate()方法,如果每次都创建新的实例的话就无法保存数据了;
2、由于Model会有耗时操作,但ViewModel随时需要回收,为了防止内存泄漏,调用Model方法时不要使用匿名内部类做回调或者直接把ViewModel传给Model。使用一个自定义的接口传给Model,Model用弱引用持有,这个可在基类处理;
3、初始化可变数据放在ViewModel构造器中;不可改变的数据在Activity处理,或者xml中写默认值;
Model
数据处理,网络请求、资源请求等耗时操作、异步操作;
需要处理的问题
ViewModel与Model内存泄漏问题
由于Model会有耗时操作,生命周期可能比ViewModel长,所以在两者交互时存在内存泄漏的问题;
在此我们可以用定义回调接口,从ViewModel传给Model,在Model中弱引用持有,Model进行回调时注意判空。这些我们使用泛型写在基类里面。
1、Model中持有接口;
public abstract class BaseModel<I> {
/**
* 回调给ViewModel的接口
*/
protected WeakReference<I> iCallBackWeakRef;
public BaseModel(I iCallBack) {
iCallBackWeakRef = new WeakReference<>(iCallBack);
}
2、ViewModel必然持有Model,我们写在基类;
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);
}