Android Jetpack 之LiveData使用及原理

LiveData

Jetpack已经出来很久了,虽然挺好用但是说实话对其原理理解还是有限,所以抽空来研究一下Jetpack各个功能的原理。

LiveData 是一种可观察的数据存储器类。与常规的可观察类不同,LiveData 具有生命周期感知能力,意指它遵循其他应用组件(如 Activity、Fragment 或 Service)的生命周期。这种感知能力可确保 LiveData 仅更新处于活跃生命周期状态的应用组件观察者。

通俗的说就是当liveData数据发生改变时,只有处于活跃状态的组件才能收到数据改变的回调。

LiveData使用

对于LiveData来说不需要在build.gradle额外添加引用,只需在项目的build.gradle中加上google()库即可,一般新建工程时候默认就有引入了google()

allprojects {
    repositories {
        google()
        jcenter()
    }
}

首先先简单的演示LiveData的使用:
我们添加两个按钮,第一个是给LiveData添加注册函数,就是对它进行观察。第二个按钮用来改变LiveData所持有的数据。


<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical"
    tools:context=".MainActivity">

    <Button
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="注册observer"
        android:onClick="onClick"/>

    <Button
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="改变数据"
        android:onClick="onClick2"/>

LinearLayout>

在对应的activity中进行相应的操作:

import androidx.appcompat.app.AppCompatActivity;
import androidx.lifecycle.MutableLiveData;
import android.os.Bundle;
import android.util.Log;
import android.view.View;

public class MainActivity extends AppCompatActivity {

    MutableLiveData<String> liveData;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        liveData = new MutableLiveData<>();
        //为livedata设置一个默认值 只能在主线程中调用 如果要在子线程中更新可以调用postValue(T)方法
        liveData.setValue("liveData默认值");
    }

    public void onClick(View view) {
    	//点击第一个按钮  添加观察回调
        liveData.observe(this,(String data)->{
            Log.d("gsy","data change  ="+data);
        });
    }

    public void onClick2(View view) {
    	//改变liveData数据
        liveData.setValue("改变了liveData的数据");
    }
}

运行起来发现当点击注册按钮时会触发回调,打印如下log,是不是有点粘性事件的意思:

2020-09-09 16:46:38.704 8763-8763/com.***.livedata D/gsy: data change  =liveData默认值

当点击改变数据时候打印如下log:

2020-09-09 16:46:53.770 8763-8763/com.***.livedata D/gsy: data change  =改变了liveData的数据

当然实际开发中肯定不会这样写,observe和setValue方法要分别写在业务逻辑需要的地方,这里只是说明一下LiveData的基本使用。很多时候LiveData都是跟ViewModel配合使用,咱们先一步一步来吧,后面再讲ViewModel。我一般都是封装一个Bus类来保存LiveData:

import androidx.lifecycle.MutableLiveData;
import java.util.HashMap;
import java.util.Map;

public class LiveDataBus {

    private static volatile LiveDataBus liveDataBus;

    private Map<String, MutableLiveData<?>> liveDataMap;
    
    private LiveDataBus(){
        liveDataMap = new HashMap<>();
    }
    //DCL单例
    public static LiveDataBus getInstance() {
        if (liveDataBus == null) {
            synchronized (LiveDataBus.class){
                if (liveDataBus == null){
                    liveDataBus = new LiveDataBus();
                }
            }
        }
        return liveDataBus;
    }
    
    //存取一体
    public<T> MutableLiveData<T> with(String key,Class<T> clazz){
        if (!liveDataMap.containsKey(key)){
            liveDataMap.put(key,new MutableLiveData<>());
        }
        return (MutableLiveData<T>) liveDataMap.get(key);
    }
}

LiveData原理

我个人看源码或者框架时候一般都是带着一个目的,因为源码性的东西一般比较复杂,不可能每行代码都能看懂。所以最好带着问题看源码。对于LiveData来说问题可以有如下两个:

  1. 注册观察者时候的流程
  2. 数据改变时候是如何回调的

1.下面就来进入源码中吧。首先先看注册观察的流程,

liveData.observe(this,(String data)->{
     Log.d("gsy","data change 1 ="+data);
});

我这里用了lambda表达式,可能不熟悉的小伙伴会看的有点迷糊,我换一种写法大家应该都能明白:

liveData.observe(this, new Observer<String>() {
       @Override
       public void onChanged(String s) {
            Log.d("gsy","data change 1 ="+s);
       }
});

我们就点进去observe方法:

    @MainThread
    public void observe(@NonNull LifecycleOwner owner, @NonNull Observer<? super T> observer) {
        assertMainThread("observe");
        if (owner.getLifecycle().getCurrentState() == DESTROYED) {
            // ignore
            return;
        }
        LifecycleBoundObserver wrapper = new LifecycleBoundObserver(owner, observer);
        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);
    }

首先observe需要传入两个参数,LifecycleOwner 和Observer。还记得注册时候吗,第一个参数我们传的是this,所以先找一下AppCompatActivity的父类,看哪个父类是实现了LifecycleOwner 这个接口。点了三次在一个叫ComponentActivity发现了如下代码:

public class ComponentActivity extends androidx.core.app.ComponentActivity implements
        LifecycleOwner,
        ViewModelStoreOwner,
        SavedStateRegistryOwner,
        OnBackPressedDispatcherOwner {

原来是ComponentActivity 实现了LifecycleOwner的接口。继续回到observe方法:

if (owner.getLifecycle().getCurrentState() == DESTROYED) {
     // ignore
     return;
}

这几行代码相信大家都能理解,如果组件当前是DESTROYED状态,就不去注册观察方法。接着new一个LifecycleBoundObserver ,它是LiveData的一个内部类:

LifecycleBoundObserver wrapper = new LifecycleBoundObserver(owner, observer);
ObserverWrapper existing = mObservers.putIfAbsent(observer, wrapper);

新建一个 LifecycleBoundObserver 将我们的 LifecycleOwner 和 observer保存起来,然后调用 mObservers.putIfAbsent(observer, wrapper) 将observer和wrapper分别作为key和value存入Map中,mObservers 实际上是一个Map集合:

private SafeIterableMap<Observer<? super T>, ObserverWrapper> mObservers =
            new SafeIterableMap<>();

接下来看下LifecycleBoundObserver 源码:

class LifecycleBoundObserver extends ObserverWrapper implements GenericLifecycleObserver {
        @NonNull
        final LifecycleOwner mOwner;

        LifecycleBoundObserver(@NonNull LifecycleOwner owner, Observer<? super 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) {
                removeObserver(mObserver);
                return;
            }
            activeStateChanged(shouldBeActive());
        }

        @Override
        boolean isAttachedTo(LifecycleOwner owner) {
            return mOwner == owner;
        }

        @Override
        void detachObserver() {
            mOwner.getLifecycle().removeObserver(this);
        }
    }

LifecycleBoundObserver 继承自 ObserverWrapper 并实现了 GenericLifecycleObserver接口,而 GenericLifecycleObserver 接口又继承自 LifecycleObserver 接口,根据 Lifecycle 的特性,实现了LifecycleObserver接口并且加入 LifecycleOwner 的观察者里就可以感知或主动获取 LifecycleOwner 的状态。那么LifecycleBoundObserver 就具备了感知组件声明周期的能力。

到这一步注册还没算完,大家应该都知道当调用observe方法时,如果liveData之前执行过setValue或者postValue也会触发oberve的回调,意思就是先赋值再注册观察者,也会触发观察者回调,这部分逻辑也是在observe中,所以继续回到observe方法,在这个方法最后:

owner.getLifecycle().addObserver(wrapper);

addObserver是Lifecycle的抽象方法,真正实现的地方在LifecycleRegistry,继续跟踪addObserver方法:

    @Override
    public void addObserver(@NonNull LifecycleObserver observer) {
        //省略代码
        while ((statefulObserver.mState.compareTo(targetState) < 0
                && mObserverMap.contains(observer))) {
            pushParentState(statefulObserver.mState);
            //关键代码
            statefulObserver.dispatchEvent(lifecycleOwner, upEvent(statefulObserver.mState));
            popParentState();
            // mState / subling may have been changed recalculate
            targetState = calculateTargetState(observer);
        }
		//省略代码
    }

代码进入while循环,调用LifecycleRegistry的内部类ObserverWithState中的dispatchEvent方法:

    static class ObserverWithState {
        State mState;
        LifecycleEventObserver mLifecycleObserver;

        ObserverWithState(LifecycleObserver observer, State initialState) {
            mLifecycleObserver = Lifecycling.lifecycleEventObserver(observer);
            mState = initialState;
        }

        void dispatchEvent(LifecycleOwner owner, Event event) {
            State newState = getStateAfter(event);
            mState = min(mState, newState);
            //关键代码
            mLifecycleObserver.onStateChanged(owner, event);
            mState = newState;
        }
    }

先看下mLifecycleObserver,也就是LifecycleEventObserver,这是个接口,显然会有其实现类。

public interface LifecycleEventObserver extends LifecycleObserver {
    /**
     * Called when a state transition event happens.
     *
     * @param source The source of the event
     * @param event The event
     */
    void onStateChanged(@NonNull LifecycleOwner source, @NonNull Lifecycle.Event event);
}

LifecycleEventObserver接口的其中一个实现类就是LifecycleBoundObserver,所以这里就调用到了LifecycleBoundObserver的onStateChanged方法:

        @Override
        public void onStateChanged(LifecycleOwner source, Lifecycle.Event event) {
            if (mOwner.getLifecycle().getCurrentState() == DESTROYED) {
                removeObserver(mObserver);
                return;
            }
            //关键代码
            activeStateChanged(shouldBeActive());
        }

继续跟踪:

void activeStateChanged(boolean newActive) {
     //省略
     if (mActive) {
          dispatchingValue(this);
     }    
}

注意传入参数不为null:

    @SuppressWarnings("WeakerAccess") /* synthetic access */
    void dispatchingValue(@Nullable ObserverWrapper initiator) {
        if (mDispatchingValue) {
            mDispatchInvalidated = true;
            return;
        }
        mDispatchingValue = true;
        do {
            mDispatchInvalidated = false;
            if (initiator != null) {
            	//进入这里
                considerNotify(initiator);
                initiator = null;
            } else {
                for (Iterator<Map.Entry<Observer<? super T>, ObserverWrapper>> iterator =
                        mObservers.iteratorWithAdditions(); iterator.hasNext(); ) {
                    considerNotify(iterator.next().getValue());
                    if (mDispatchInvalidated) {
                        break;
                    }
                }
            }
        } while (mDispatchInvalidated);
        mDispatchingValue = false;
    }

进入considerNotify:

    private void considerNotify(ObserverWrapper observer) {
        if (!observer.mActive) {
            return;
        }
        if (!observer.shouldBeActive()) {
            observer.activeStateChanged(false);
            return;
        }
        if (observer.mLastVersion >= mVersion) {
            return;
        }
        observer.mLastVersion = mVersion;
        //noinspection unchecked
        observer.mObserver.onChanged((T) mData);
    }

前面两个判断都是跟生命周期有关,我们先不用关注,第三个if是关键所在,这俩变量初始值都是-1,所以看起来 这里就会return了,但是别忘了我们在调用obeserve之前设置了默认值。

int mLastVersion = START_VERSION;
private int mVersion = START_VERSION;
    @MainThread
    protected void setValue(T value) {
        assertMainThread("setValue");
        //关键代码
        mVersion++;
        mData = value;
        dispatchingValue(null);
    }

所以当走到if (observer.mLastVersion >= mVersion)这里时候,mLastVersion =-1,mVersion=0。所以代码会继续运行下去:

observer.mLastVersion = mVersion;
//noinspection unchecked
observer.mObserver.onChanged((T) mData);

调用到注册时候的回调方法。这就是为啥LiveData设置值后再注册,也会触发回调的原因,当年可是被这个坑坑的不轻。到此第一个问题算是解决了。

  1. 数据改变时候是如何回调的。
    那就要看更新数据时候发生了什么,就以setValue为例:
    @MainThread
    protected void setValue(T value) {
        assertMainThread("setValue");
        mVersion++;
        mData = value;
        dispatchingValue(null);
    }

将value赋值给mData ,然后调用dispatchingValue注意这里传入的是null:

    @SuppressWarnings("WeakerAccess") /* synthetic access */
    void dispatchingValue(@Nullable ObserverWrapper initiator) {
        if (mDispatchingValue) {
            mDispatchInvalidated = true;
            return;
        }
        mDispatchingValue = true;
        do {
            mDispatchInvalidated = false;
            if (initiator != null) {
                considerNotify(initiator);
                initiator = null;
            } else {
           		//关键代码
                for (Iterator<Map.Entry<Observer<? super T>, ObserverWrapper>> iterator =
                        mObservers.iteratorWithAdditions(); iterator.hasNext(); ) {
                    //关键代码
                    considerNotify(iterator.next().getValue());
                    if (mDispatchInvalidated) {
                        break;
                    }
                }
            }
        } while (mDispatchInvalidated);
        mDispatchingValue = false;
    }

这就很明显了,从Map中取出保存的ObserverWrapper,然后在considerNotify中调用onChanged回调。代码比较简单就不再贴了。

总结

LiveData使用在组件通信方面还是非常方便的,它主要是依赖于Lifecycle去实现的,其实现原理感觉在Jetpack中算是比较简单的了。关于生命周期这块就不再去写了,有兴趣的小伙伴可以去看下Lifecycle源码。

你可能感兴趣的:(java,android,android,java)