Android开发——架构组件LiveData源码解析

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/SEU_Calvin/article/details/82256693
近期的业务代码中使用到了LiveData,
研究了一下发现很好用,因此总结整理出了此篇学习笔记。希望各位多批评指正。

1. LiveData概述

简单地来说,LiveData就是一个持有数据的类。

  • LiveData中的数据可以被观察者订阅,当数据被修改时通知观察者。观察者包括Fragment、Activity以及Service等。
  • LiveData能够感知观察者的生命周期。只有在观察者处于激活状态(STARTED、RESUMED)才会收到数据更新;并在未激活时自动解注册观察者,避免崩溃,且减少内存泄露。
  • 当我们采用LiveData保存数据时,数据和组件的分离使得组件在ReCreate时保证数据不丢失。
需要注意的是:
(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<String> mData;

    public MutableLiveData<String> 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<String>() {
            @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<Integer> {
    private static MyLiveData mData;
    private WeakReference<Context> 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。

  • onActive(),当处于激活状态的observer个数从0到1时,该方法会被调用。
  • onInactive() ,当处于激活状态的observer个数从1变为0时,该方法会被调用。

3. LiveData源码解析

主要从以下三个方面进行分析:

  • 在Fragment/Activity中通过LiveData.observe()注册观察者
  • 根据Fragment/Activity生命周期的变化,实时移除观察者;或者从后台转到前台时通知观察者更新数据
  • 当调用LiveData的setValue()或postValue()方法后,通知观察者更新数据

3.1 注册观察者

public void observe(@NonNull LifecycleOwner owner, @NonNull Observer<T> 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<T> 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

猜你喜欢

转载自blog.csdn.net/SEU_Calvin/article/details/82256693