1.在我们写APP的时候经常会遇到这种情况,点击一个按钮后,通过网络异步操作从后台获取信息,然后再展示到UI,例如
public class MyActivity extends BaseActivity {
private void getUser(){
LoadingDialog loadingDialog=new LoadingDialog(this,"加载中");
loadingDialog.show();
Request request = new Request.Builder()
.url("getuser.php")
.build();
Call call =HttpUtils.getInstance().newCall(request);
call.enqueue(new Callback() {
@Override
public void onFailure(Call call, IOException e) {
}
@Override
public void onResponse(Call call, Response response) throws IOException {
//更新UI
}
});
}
}
2.由于子线程中不能直接操作UI,所以我们这个时候我们需要利用Handler或者其他方式在主线程中进行
private static <T> Callback getCallBack() {
final Handler handler = new Handler() {
@Override
public void handleMessage(Message msg) {
//更新UI
}
};
return new Callback() {
@Override
public void onFailure(Call call, IOException e) {
}
@Override
public void onResponse(Call call, Response response) throws IOException {
Message message = handler.obtainMessage(1, response);
handler.sendMessage(message);
}
};
}
3.Handler在创建的时候会自动持有Activity对象,所以在Activity被系统回收时,会没办法释放导致内存泄漏,如果去网上搜索,大多数都是让你使用弱引用或者静态内部类来解决,但是这两种方式都很麻烦而且使代码变的很难看,ViewModel+Data Binding是更好的方法
4.ViewModel有以下好处
- ViewModel不会持有Activity对象
- ViewModel会监视Activity的生命周期,在Activity的生命周期里可能触发多次OnCreate,但是ViewModel只会创建一次
- ViewModel可以自动帮你保存数据,让Activity销毁再创建后可以恢复数据
5.ViewModel代码如下,网络请求开始时会设置Result为0,结束时会设置Result为1,这里我只是打个比方,你也可以使用ObservableField或者BaseObservable传递更复杂的数据,UserInfoViewModel也可以继承AndroidViewModel,它是一个拥有上下文的ViewModel
public class UserInfoViewModel extends ViewModel {
private final ObservableInt mResult=new ObservableInt();
public ObservableInt getResult() {
return mResult;
}
public void getUser(){
Request request = new Request.Builder()
.url("getuser.php")
.build();
Call call =HttpUtils.getInstance().newCall(request);
mResult.set(0);
call.enqueue(new Callback() {
@Override
public void onFailure(Call call, IOException e) {
}
@Override
public void onResponse(Call call, Response response) throws IOException {
mResult.set(1);
}
});
}
}
6.下面是Activity里的代码,Activity可以监视Result来更新UI
private void subscribeUi() {
mUserInfoViewModel.getResult().addOnPropertyChangedCallback(new Observable.OnPropertyChangedCallback() {
@Override
public void onPropertyChanged(Observable sender, int propertyId) {
int result=mUserInfoViewModel.getResult().get();
switch (result){
case 0:
mLoadingDialog.show("加载中");
break;
case 1:
mLoadingDialog.dismiss();
ToastUtils.show("获取数据成功");
break;
default:
break;
}
}
});
}
7.上面的DataBinding也可以换成LiveData,其区别是
- ObservableField只有在数据发生改变时UI才会收到通知,而LiveData不同,只要你postValue或者setValue,UI都会收到通知,不管数据有无变化
- LiveData能感知Activity的生命周期,在Activity不活动的时候不会触发,例如一个Activity不在任务栈顶部,在Activity重新激活的时候(OnResume)时会主动触发一次