近期的业务代码中使用到了LiveData,
研究了一下发现很好用,因此总结整理出了此篇学习笔记。希望各位多批评指正。
1. LiveData概述
简单地来说,LiveData就是一个持有数据的类。
需要注意的是:
(1)当观察者从后台到前台来时,LiveData能够将最新的数据通知给观察者,保证数据实时更新;
(2)组件在ReCreate时,会经历N个生命周期方法,但是ViewModel还是之前的对象。因此LiveData常结合VM使用。
2. LiveData的使用
LiveData的使用有两种方式,结合ViewModel使用LiveData对象或者直接继承LiveData类。
2.1 结合ViewModel使用LiveData对象
以一个简单的例子展示,使用LiveData子类MutableLiveData,维护一个String类型的数据:
public class MyViewModel extends ViewModel{
// Create a LiveData with a String
private MutableLiveData mData;
public MutableLiveData getCurrentData() {
if (mData == null) {
mData = new MutableLiveData<>();
}
return mData;
}
}
接着,创建并注册观察者:
public class LiveDataFragment extends Fragment{
private MyViewModel mViewModel;
@Override
public void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
//这里执行注册
mViewModel = ViewModelProviders.of(this).get(MyViewModel.class);
mViewModel.getCurrentData().observe(this, new Observer() {
@Override
public void onChanged(@Nullable String data) {
//LiveData数据变化后的回调
}
});
}
}
使用setValue更新LiveData中的数据
mViewModel.getCurrentData().setValue("yanxuan");
2.2 直接继承LiveData类
除了直接使用LiveData对象,还可以通过直接继承LiveData类来定义适合特定需求的LiveData。下面的例子使用LiveData简单地实现一个资源共享的需求。
public class MyLiveData extends LiveData {
private static MyLiveData mData;
private WeakReference mContext;
public static MyLiveData getInstance(Context context){
if (mData == null){
mData = new MyLiveData(context);
}
return mData;
}
private MyLiveData(Context context){
mContext = new WeakReference<>(context);
}
@Override
protected void onActive() {
super.onActive();
registerReceiver();
}
@Override
protected void onInactive() {
super.onInactive();
unregisterReceiver();
}
private void registerReceiver() {
IntentFilter intentFilter = new IntentFilter();
intentFilter.addAction(WifiManager.RSSI_CHANGED_ACTION);
mContext.get().registerReceiver(mReceiver, intentFilter);
}
private void unregisterReceiver() {
mContext.get().unregisterReceiver(mReceiver);
}
private BroadcastReceiver mReceiver = new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
mData.setValue(getWifiLevel(intent));
}
};
}
在onActive()和onInactive()方法中分别注册和反注册Wifi信号强度的广播,并且在广播接收器中更新数据。 在使用的时候就可以通过MyLiveData.getInstance().observe()方法来添加观察者对象和observer。
3. LiveData源码解析
主要从以下三个方面进行分析:
3.1 注册观察者
public void observe(@NonNull LifecycleOwner owner, @NonNull Observer observer) {
if (owner.getLifecycle().getCurrentState() == DESTROYED) {
// ignore
return;
}
//将LifecycleOwner对象和Observer对象封装成LifecycleBoundObserver对象
LifecycleBoundObserver wrapper = new LifecycleBoundObserver(owner, observer);
//mObservers(一个类似Map的容器)的putIfAbsent()方法
//用于判断容器中的observer(key)是否有已经和wrapper(value)关联
//如果已关联则返回关联值,否则关联之后并返回wrapper。
ObserverWrapper existing = mObservers.putIfAbsent(observer, wrapper);
if (existing != null && !existing.isAttachedTo(owner)) {
throw new IllegalArgumentException("Cannot add the same observer"
+ " with different lifecycles");
}
if (existing != null) {
return;
}
//注册
owner.getLifecycle().addObserver(wrapper);
}
首先将LifecycleOwner对象和Observer对象封装成LifecycleBoundObserver对象,LifecycleBoundObserver是一个内部类,它继承自ObserverWrapper,并实现了GenericLifecycleObserver,而GenericLifecycleObserver继承了LifecycleObserver接口。当组件生命周期变化时会通过onStateChanged()方法回调过来。
3.2 感知生命周期变化
通过上面的分析,观察者就是LifecycleBoundObserver对象,下面我们看一下LifecycleBoundObserver具体实现。
class LifecycleBoundObserver extends ObserverWrapper implements GenericLifecycleObserver {
@NonNull final LifecycleOwner mOwner;
LifecycleBoundObserver(@NonNull LifecycleOwner owner, Observer observer) {
super(observer);
mOwner = owner;
}
@Override
boolean shouldBeActive() {
return mOwner.getLifecycle().getCurrentState().isAtLeast(STARTED);
}
@Override
public void onStateChanged(LifecycleOwner source, Lifecycle.Event event){
if (mOwner.getLifecycle().getCurrentState() == DESTROYED) {
//DESTROYED状态下移除观察者
//该行代码会间接调用下面的detachObserver()方法
removeObserver(mObserver);
return;
}
//判断是否处于actived状态,并将结果作为参数传递给activeStateChanged()
activeStateChanged(shouldBeActive());
}
@Override
boolean isAttachedTo(LifecycleOwner owner) {
return mOwner == owner;
}
@Override
void detachObserver() {
mOwner.getLifecycle().removeObserver(this);
}
}
当组件(Fragment/Activity)生命周期发生变化时,onStateChanged()方法会被调用。如果当前处于Lifecycle.State.DESTROYED时,会自动将观察者移除;若当前处于ACTIVE状态,则继续调用activeStateChanged()方法,该方法位于父类ObserverWrapper中:
void activeStateChanged(boolean newActive) {
//新状态和之前状态相同的情况,直接返回
if (newActive == mActive) {
return;
}
// immediately set active state, so we'd never dispatch anything to inactive owner
mActive = newActive;
boolean wasInactive = LiveData.this.mActiveCount == 0;
LiveData.this.mActiveCount += mActive ? 1 : -1;
if (wasInactive && mActive) {
onActive(); //空实现
}
if (LiveData.this.mActiveCount == 0 && !mActive) {
onInactive(); //空实现
}
if (mActive) {
dispatchingValue(this); //数据通知
}
}
可以看到,若新状态和之前状态相同,则不进行不处理。 并且,当处于激活状态的observer个数从0到1时,调用onActive(); 当处于激活状态的observer个数从1到0时,调用onInactive()。
以上的onActive()和onInactive()都是空实现的方法,继承类可以选择去实现
最后调用的是dispatchingValue()进行数据变化时的消息通知,最终的回调代码如下。mObserver即为调用observe()注册时传入的Observer对象。
observer.mObserver.onChanged((T) mData);
3.3 改变数据后的通知逻辑
LiveData提供了两种改变数据的方法:在主线程调用的setValue()方法,以及在子线程中调用的postValue()方法。我们先看setValue()方法的具体实现:
protected void setValue(T value) {
assertMainThread("setValue");
mVersion++;
mData = value;
dispatchingValue(null);
}
首先判断当前线程是否是主线程,不是就会抛出异常。将数据赋值给mData后,调用了dispatchingValue()进行数据通知,该方法3.2中已经讨论过了。
protected void postValue(T value) {
boolean postTask;
synchronized (mDataLock) {
postTask = mPendingData == NOT_SET;
//数据赋值给mPendingData,等待在主线程中使用
mPendingData = value;
}
if (!postTask) {return;}
ArchTaskExecutor.getInstance().postToMainThread(mPostValueRunnable);
}
private final Runnable mPostValueRunnable = new Runnable() {
@Override
public void run() {
Object newValue;
synchronized (mDataLock) {
newValue = mPendingData;
mPendingData = NOT_SET;
}
//最终调用setValue()
setValue((T) newValue);
}
};
在postValue()方法中,通过ArchTaskExecutor实现在主线程中执行mPostValueRunnable中的内容,而在mPostValueRunnable的run()中最终会调用setValue()方法来实现改变LiveData中的数据。
4. 总结
结合ViewModel的生命周期特点,LiveData很适合用于Fragment与Fragment之间的通信、Fragment与Activity之间的通信等。
需要注意的是,数据发送方和接收方传给方法ViewModelProviders.of()的对象必须一致,
最终得到的才是同一个ViewModel对象。
转载请注明出处:https://blog.csdn.net/SEU_Calvin/article/details/82256693