本文会深入解析LiveData的原理及其应用
1、背景
之前的业务中有一个问题,我一个异步数据,供一个Activity使用,如果用强引用的callback,一是会造成内存泄漏,二是如果Activity destroy了,回调会有问题。另外一种方案是采用weakreference的callback,但这样一来就不能使用匿名内部类,使用起来不是很方便,所以研究一下能不能用LiveData来实现。
2、实现
首先是异步的DataLoader:
public class DataLoader {
public Observable<UserInfoBean> getUserInfoQuickly(String name) {
return Observable.just(name)
.map(new Func1<String, UserInfoBean>() {
@Override
public UserInfoBean call(String s) {
int id = new Random().nextInt(1000);
return new UserInfoBean(s, id, id + "");
}
})
.delay(1, TimeUnit.SECONDS);
}
public Observable<UserInfoBean> getUserInfoSlowly(String name) {
return Observable.just(name)
.map(new Func1<String, UserInfoBean>() {
@Override
public UserInfoBean call(String s) {
int id = new Random().nextInt(1000);
return new UserInfoBean(s, id, id + "");
}
})
.delay(5, TimeUnit.SECONDS);
}
}
使用LiveData的LiveDataLoader:
public class LiveDataLoader {
private DataLoader loader = new DataLoader();
// private MutableLiveData<UserInfoBean> userInfo = new MutableLiveData<>();
public LiveData<UserInfoBean> getUserInfoQuickly(String name) {
final MutableLiveData<UserInfoBean> userInfo = new MutableLiveData<>();
loader.getUserInfoQuickly(name)
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(new Action1<UserInfoBean>() {
@Override
public void call(UserInfoBean userInfoBean) {
userInfo.setValue(userInfoBean);
}
});
return userInfo;
}
public LiveData<UserInfoBean> getUserInfoSlowly(String name) {
final MutableLiveData<UserInfoBean> userInfo = new MutableLiveData<>();
loader.getUserInfoSlowly(name)
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(new Action1<UserInfoBean>() {
@Override
public void call(UserInfoBean userInfoBean) {
userInfo.setValue(userInfoBean);
}
});
return userInfo;
}
}
在Activity中使用:
public class ViewModelDemo2 extends AppCompatActivity {
private ActivityViewModelDemo2Binding binding;
private UserInfoViewModel viewModel;
private LiveDataLoader liveDataLoader = new LiveDataLoader();
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
binding = DataBindingUtil.setContentView(this, R.layout.activity_view_model_demo2);
viewModel = ViewModelProviders.of(this).get(UserInfoViewModel.class);
binding.setUserinfo(viewModel);
binding.setHandler(this);
binding.setLifecycleOwner(this);
// liveDataLoader = ViewModelProviders.of(this).get(LiveDataLoader.class);
}
public void doLoadUserInfo1() {
liveDataLoader.getUserInfoQuickly(viewModel.editName.getValue())
.observe(this, new Observer<UserInfoBean>() {
@Override
public void onChanged(@Nullable UserInfoBean userInfoBean) {
Toast.makeText(ViewModelDemo2.this, userInfoBean.toString(), Toast.LENGTH_SHORT).show();
}
});
}
public void doLoadUserInfo2() {
liveDataLoader.getUserInfoSlowly(viewModel.editName.getValue())
.observe(this, new Observer<UserInfoBean>() {
@Override
public void onChanged(@Nullable UserInfoBean userInfoBean) {
Toast.makeText(ViewModelDemo2.this, userInfoBean.toString(), Toast.LENGTH_SHORT).show();
}
});
}
}
LiveDataLoader并没有继承ViewModel,关于LiveData是否需要结合ViewModel使用,官网文档中有这样一段描述:
Note: Make sure to store LiveData objects that update the UI in ViewModel objects, as opposed to an activity or fragment, for the following reasons:
-
To avoid bloated activities and fragments. Now these UI controllers are responsible for displaying data but not holding data state.
-
To decouple LiveData instances from specific activity or fragment instances and allow LiveData objects to survive configuration changes.
大概意思就是说LiveData要结合ViewModel使用
其实只要不是跟界面结合很紧,单独使用也是可以的,而且这样一来可以在使用时才注册回调,非常方便
LiveData可以理解成带生命周期的callback
3、深入分析LiveData的原理
LiveData调用observe的时候,会把Activity的实例和observer传进去:
首先用一个LifecycleBoundObserver把LifeCycleOwner和Observer包进去,放在一个类似map的容器里,这就是实现回调功能的基础
owner.getLifecycle().addObserver(wrapper);
这句代码会把之前那个wrapper放到LifeCycle里面去,这个LifeCycle是个啥:
实际调用的是SupportActivity的实现:
addObserver的具体实现:
这里也会把observer装进这个mObserverMap里面,这里会关系到后面当Activity destroy了,这些observer会remove掉
当LiveData调用setValue的时候:
会调dispatchingValue:
会遍历mObservers,然后调用considerNotify实现回调:
那么是怎么实现当Activity destroy的时候,remove掉相关的observer呢?
当Activity或者Fragment状态变化,比如destroy的时候,会调用LifecycleRegistry的moveToState
接着调用LifecycleRegistry.sync()
LifecycleRegistry.backwardPass()
ObserverWithState.dispatchEvent()
最后会调到关键的函数:LiveData.onStateChanged,就在这里把observer remove掉: