开发中经常要表示一个数据当前状态,比如加载中、加载错误、空列表。这个时候如果我们每个地方自己去处理就很麻烦,如果我们使用的viewmodel自己就能表示这些状态岂不美哉?
另外数据加载中还经常需要处理取消的逻辑,比如使用rxjava,自动管理disposable就更好了~
说干就干~封装一个BaseViewModel~
package cn.icetower.basebiz.vm;
import androidx.annotation.CallSuper;
import androidx.annotation.NonNull;
import androidx.lifecycle.MutableLiveData;
import androidx.lifecycle.ViewModel;
import io.reactivex.rxjava3.disposables.CompositeDisposable;
import io.reactivex.rxjava3.disposables.Disposable;
/**
* ViewModel基类,带状态,可设置用来表示主要状态的数据类型。<br>
* 一个Activity或Fragment中可以有多个ViewModel,使用多个ViewModel的情况可以用来做局部加载和刷新展示。
*
*
* @author renpeng
* @version 1.0
* @description
* @since 2020/8/20
*/
public abstract class BaseViewModel<MainData> extends ViewModel {
public static final int STATUS_IDLE = 0; //空闲(加载完成)
public static final int STATUS_LOADING = 1; //加载中
public static final int STATUS_ERROR = 2;//异常
public static final int STATUS_EMPTY = 3;//无数据
public static final int STATUS_CANCEL = 4;//用户取消
private volatile int status = STATUS_IDLE; //当前viewmodel的主要状态,外部可以通过这个标识来作UI展示
private CompositeDisposable compositeDisposable;
protected MutableLiveData<MainData> mainData = new MutableLiveData<>();
protected int page = 1;//方便子类分布加载时使用
/**
* 直接获取到mainData对象,但不进行任何额外的操作
* @param <T>
* @return
*/
public <T> MutableLiveData<MainData> getMainData(){
return mainData;
}
protected void setLoading(){
setLoading(mainData.getValue());
}
protected void setLoading(MainData data){
this.status = STATUS_LOADING;
mainData.postValue(data);
}
protected void setError(MainData data){
this.status = STATUS_ERROR;
mainData.postValue(data);
}
protected void setIdle(@NonNull MainData data){
this.status = STATUS_IDLE;
mainData.postValue(data);
}
/**
* 加载状态,loading状态下默认会收到上次保存的值
*/
public boolean isLoading(){
return this.status == STATUS_LOADING;
}
/**
* 错误状态
*/
public boolean isError(){
return this.status == STATUS_ERROR;
}
/**
* 数据量为0
*/
public boolean isEmpty(){
return this.status == STATUS_EMPTY;
}
/**
* 空闲状态
*/
public boolean isIdle(){
return this.status == STATUS_IDLE;
}
public boolean isIdleWithData(){
return isIdle() && mainData.getValue() != null;
}
/**
* 一般用来设置列表数据大小为0
* @param data
*/
protected void setEmpty(MainData data){
this.status = STATUS_ERROR;
mainData.postValue(data);
}
@Override
@CallSuper
protected void onCleared() {
super.onCleared();
if(compositeDisposable != null){
compositeDisposable.dispose();
compositeDisposable = null;
}
}
public void addDisposable(Disposable disposable){
if(compositeDisposable == null){
compositeDisposable = new CompositeDisposable();
}
compositeDisposable.add(disposable);
}
}
另外:一个Actvity或Fragment中可以使用多个viewmodel,用来加载不同部分的数据,可以做局部加载或刷新用,更加方便~
要使用参数可以通过在子类定义成员变量,使用时set赋值,然后在doLoadData中使用。