本文已收录到GitHub/Android-Notes中,这儿有 Android 进阶生长知识系统笔记,有情投意合的朋友,关注大众号 [小尘Android专栏] 跟我一同生长。

前言

Jetpack 是一个由多个库组成的套件,可协助开发者遵从最佳做法,削减样板代码。假如项目选用 MVVM 架构,那么 Jetpack 里边的架构相关的组件便是为MVVM 量身定制的,并且现在面试Jetpack也是必问项,但是许多开发者对Jetpack中的一些中心组件都只停留在会用的阶段,对其原理及源码却是一知半解甚至根本没了解过,因而整理了一个系列来协助有需求的小伙伴理解Jetpack设计思想和原理

Jetpack核心架构组件源码解析系列(2):LiveData运用与原理及源码分析

正文

LiveData是什么

LiveData,它是一个数据持有类,它内部可以持有一个恣意类型的目标。LiveData选用了观察者模式,观察者可观察其持有的目标,只需目标一发生改动,就会告诉并将持有目标回调给观察者。一起LiveData的观察者还具备感知组件(Activity、Fragment等)生命周期改动的才能,当组件的生命周期处于不同的状况时,能作出相对应的处理。

LiveData的根本运用

LiveData的根本运用示例:

public class MainActivity extends AppCompatActivity {
    //LiveData是抽象类 MutableLiveData是其子类 
    //所以咱们在运用的时分都是运用MutableLiveData
    //目标所声明的泛型<String>便是当时这个LiveData所持有的目标的类型,可以是恣意类型的目标
    MutableLiveData<String> liveData;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        liveData = new MutableLiveData<>();
        //注册观察者
        liveData.observe(this, new Observer<String>() {
            @Override
            //s便是LiveData持有的数据
            public void onChanged(String s) {
                Toast.makeText(MainActivity.this,s,Toast.LENGTH_LONG).show();
            }
        });
    }
    /**
     * 发送告诉
     * @param view
     */
    public void sendMessage(View view) {
        //改动LiveData持有的数据
        liveData.setValue("aaaaaaaaaaaa");
    }
}

当咱们经过点击事情调用liveData.setValue(“”)的时分,就会改动LiveData所持有的数据,这个LiveData目标中的观察者就会被回调,一起会将持有的数据传给观察者,天然观察者中的事务逻辑也会被调用。并且要注意,LiveData供给了两个改动持有数据的办法setValue()以及postValue(),那么他们的区别是什么呢?咱们可以先稍微看下源码:

public abstract class LiveData<T> {
    ...省掉...
    //切换线程的Runnable
    private final Runnable mPostValueRunnable = new Runnable() {
        @Override
        public void run() {
            Object newValue;
            synchronized (mDataLock) {
                newValue = mPendingData;
                mPendingData = NOT_SET;
            }
            //最终仍是调用setValue
            setValue((T) newValue);
        }
    };
    protected void postValue(T value) {
        boolean postTask;
        synchronized (mDataLock) {
            postTask = mPendingData == NOT_SET;
            mPendingData = value;
        }
        if (!postTask) {
            return;
        }
        //当调用postValue的时分不论当时是什么线程,都直接切换到主线程
        ArchTaskExecutor.getInstance().postToMainThread(mPostValueRunnable);
    }
    @MainThread
    protected void setValue(T value) {
        //当调用setValue的时分,会一开始判别当时是否是在主线程中调用,
        //假如不是就直接抛出异常,由此可见setValue仅限于主线程调用
        assertMainThread("setValue");
        mVersion++;
        mData = value;
        dispatchingValue(null);
    }
    private static void assertMainThread(String methodName) {
        if (!ArchTaskExecutor.getInstance().isMainThread()) {
            throw new IllegalStateException("Cannot invoke " + methodName + " on a background"
                    + " thread");
        }
    }
      ...省掉...
}

当调用setValue()的时分,会一开始判别当时是否是在主线程中调用,假如不是就直接抛出异常,由此可见setValue()仅限于主线程调用。而当调用postValue()的时分,不论当时是什么线程,都直接切换到主线程再履行setValue()办法,所以经过源码可以很显着的看出,setValue()是在主线程顶用的,而postValua()是在子线程顶用的。

并且经过以上的内容咱们可以初步推断出以下图中内容:

Jetpack核心架构组件源码解析系列(2):LiveData运用与原理及源码分析

当咱们经过两个改动数据源的办法进行数据更新的时分,会遍历所有的观察者,然后回调其办法。但事实真的如此简略嘛?在后面的内容中咱们会得到答案!

LiveData的运用场景剖析

1、网络恳求回调

代码示例:

//网络恳求数据经过Handler来更新UI
public void handlerTest(){
        final Handler handler = new Handler(){
            @Override
            public void handleMessage(Message msg) {
                super.handleMessage(msg);
                responseContentView.setText(msg.obj.toString());
            }
        };
        new Thread(new Runnable() {
            @Override
            public void run() {
                try {
                    OkHttpClient okHttpClient = new OkHttpClient();
                    Request request = new Request.Builder()
                            .get()
                            .url("https://v.juhe.cn/historyWeather/citys")
                            .build();
                    Call call = okHttpClient.newCall(request);
                    call.clone().execute();
                    call.enqueue(new Callback() {
                        @Override
                        public void onFailure(Call call, IOException e) {
                        }
                        @Override
                        public void onResponse(Call call, Response response) throws IOException {
                            String res = response.body().string();
                            Message msg = new Message();
                            msg.obj = res;
                            msg.what = 1;
                            handler.sendMessage(msg);
                        }
                    });
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }).start();
    }

以上代码作为Android开发者看着肯定会很眼熟,当咱们进行网络加载数据时,很久以前都是经过Handler来进行UI更新的。

//网络恳求数据经过LiveData来更新UI
public void liveDataTest(){
        final MutableLiveData<String> liveData = new MutableLiveData<>();
        liveData.observe(this, new Observer<String>() {
            @Override
            public void onChanged(String s) {
                //responseContentView.setText(s);
                Toast.makeText(MainActivity.this,s,Toast.LENGTH_LONG).show();
            }
        });
        new Thread(new Runnable() {
            @Override
            public void run() {
                try {
                    OkHttpClient okHttpClient = new OkHttpClient();
                    Request request = new Request.Builder()
                            .get()
                            .url("https://v.juhe.cn/historyWeather/citys")
                            .build();
                    Call call = okHttpClient.newCall(request);
                    call.clone().execute();
                    call.enqueue(new Callback() {
                        @Override
                        public void onFailure(Call call, IOException e) {
                        }
                        @Override
                        public void onResponse(Call call, Response response) throws IOException {
                            String res = response.body().string();
                            //postValue是子线程改动LiveData所持有的数据专用的
                            liveData.postValue(res);
                        }
                    });
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }).start();
    }

咱们会发现,经过LiveData咱们同样能到达Handler的效果,以上代码咱们可以自行去进行测验。那么问题来了,已然已经有了Handler,然后LiveData的效果看起来和Handler相似,LiveData的存在必要是什么?既生瑜何生亮?天然是“亮”的才能与优势要比“瑜”突出,这一点咱们从下面组件通讯的运用内容中就可以得出结论。

2、组件通讯

//LiveData的管理器
public class LiveDataBus {
    private static LiveDataBus liveDataBus = new LiveDataBus();
    public Map<String, MutableLiveData<Object>> bus;
    private LiveDataBus(){
        bus = new HashMap<>();
    }
    public static LiveDataBus getInstance(){
        return liveDataBus;
    }
    /**
     * 添加和取LiveData目标
     * @param key
     * @param clazz
     * @param <T>
     * @return
     */
    public <T> MutableLiveData<T> putAndGetLiveData(String key,Class<T> clazz){
        if(key!=null && !bus.containsKey(key)){
            bus.put(key,new MutableLiveData<Object>());
        }
        return (MutableLiveData<T>) bus.get(key);
    }
}

封装好了之后,只需咱们在不同的组件中持有同一个LiveData目标就可以传数据以及通讯了。代码如下:

public class MainActivity extends AppCompatActivity {
    MutableLiveData<String> liveData;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        //创建一个LiveData目标,并放到LiveData管理器的Map中
        liveData = LiveDataBus.getInstance().putAndGetLiveData("lisan",String.class);
        liveData.observe(this, new Observer<String>() {
            @Override
            public void onChanged(String s) {
                Toast.makeText(MainActivity.this,s,Toast.LENGTH_LONG).show();
            }
        });
    }
}

在NextActivity中获取到同一个LiveData目标,然后经过setValue改动其所持有的数据,那么在MainActivity里边的注册的观察者就会被告诉(回调)。

public class NextActivity extends AppCompatActivity {
    MutableLiveData liveData;
    @Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_next);
        liveData = LiveDataBus.getInstance().putAndGetLiveData("lisan",String.class);
    }
    public void sendMessage(View view) {
        liveData.setValue("NextActivty里边发送了一个告诉");
    }
}

当咱们真正去跑一下以上代码的时分,会发现一个显着的问题,当咱们在NextActivity中改动数据源的时分,MainActivity中的观察者并不能立马被回调。这是为什么呢?其实在用LiveData的时分,咱们必需求遵从一个规矩,那便是观察者只有在其地点的Activity(或其他组件)是可见状况的时分才能被回调,所以当咱们在NextActivity发送告诉时,MainActivity中的观察者并不能立马收到(由于那时的MainActivity是不行见的状况),只有当MainActivity可见的时分才能收到告诉

这便是LiveData的奇特之处,也是LiveData之所以能取代一众事情分发框架的原因(包含Handler)。那为什么会这样呢,这就要归功于Lifecycle了,下面咱们会剖析Lifecycle的效果以及在LiveData中的效果。详细可看我之前这么Lifecycle的解说!

3、调用系统相机、广播等

4、与ViewModel、ROOM等合作运用

LiveData源码解读

注册观察者代码解析:

liveData.observe(this, new Observer<String>() {
            @Override
            public void onChanged(String s) {
                //responseContentView.setText(s);
                Log.e("MainActivity------>",s);
            }
        });
@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);
        //包装好的类封装到一个容器中key=观察者,value=包装类
        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;
        }
        //将上面的包装类作为观察者注册给Lifecycle,
        //说明包装类实现了Lifecycle的观察者办法,也就可以感知到组件的生命周期了
        owner.getLifecycle().addObserver(wrapper);
    }

接下来看看组件和LiveData观察者的包装类: 为了今后的扩展,定义了一个抽象类。

private abstract class ObserverWrapper {
        //观察者
        final Observer<? super T> mObserver;
        boolean mActive;
        //版本号,避免观察者重复收到消息或告诉
        int mLastVersion = START_VERSION;
        ObserverWrapper(Observer<? super T> observer) {
            mObserver = observer;
        }
        abstract boolean shouldBeActive();
        boolean isAttachedTo(LifecycleOwner owner) {
            return false;
        }
        void detachObserver() {
        }
        //当绑定的组件的生命周期发生改动的时分 经过这个API进行事情分发
        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);
            }
        }
    }

具体实现:

class LifecycleBoundObserver extends ObserverWrapper implements GenericLifecycleObserver {
        //组件(LiveData地点的Activity)
        @NonNull
        final LifecycleOwner mOwner;
        LifecycleBoundObserver(@NonNull LifecycleOwner owner, Observer<? super T> observer) {
            super(observer);
            mOwner = owner;
        }
        //当时的Activity状况是否是可见的,这儿回顾Lifecycle的状况机
        @Override
        boolean shouldBeActive() {
            return mOwner.getLifecycle().getCurrentState().isAtLeast(STARTED);
        }
        //实现GenericLifecycleObserver接口的回调,组件生命周期发生改动就会回调
        @Override
        public void onStateChanged(LifecycleOwner source, Lifecycle.Event event) {
            //为了避免造成内存泄漏 Activity生命周期结束的好把观察者移除掉
            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);
        }
    }

事情分发的会调用下面这个昂发

@SuppressWarnings("WeakerAccess") /* synthetic access */
    void dispatchingValue(@Nullable ObserverWrapper initiator) {
        if (mDispatchingValue) {
            mDispatchInvalidated = true;
            return;
        }
        mDispatchingValue = true;
        do {
            mDispatchInvalidated = false;
             //组件生命周期回调的时分走if里边
            if (initiator != null) {
                //回调绑定组件的这个观察者
                considerNotify(initiator);
                initiator = null;
            } else {
                 //setValue和postValue走这儿
                //遍历容器中所有的观察者,拿出来传入considerNotify办法
                for (Iterator<Map.Entry<Observer<? super T>, ObserverWrapper>> iterator =
                        mObservers.iteratorWithAdditions(); iterator.hasNext(); ) {
                    considerNotify(iterator.next().getValue());
                    if (mDispatchInvalidated) {
                        break;
                    }
                }
            }
        } while (mDispatchInvalidated);
        mDispatchingValue = false;
    }
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);
    }

到这儿停止根本LiveData观察者被组件的生命周期改动回调的流程就走完了。接下来便是LiveData中setValue()办法履行的时分是怎么被调用观察者的:

    @MainThread
    protected void setValue(T value) {
        //判别是否当时是主线程
        assertMainThread("setValue");
        //LiveData的版本号+1
        mVersion++;
        //保存设置进来的目标
        mData = value;
        //调用观察者(下面的流程就不了,上面已经走完了)
        dispatchingValue(null);
    }

mVersion和observer.mLastVersion是怎么一回事呢?假定我AActivity中注册了一个观察者,假如AActivity不断的在活泼与不活泼之间进行切换,那么considerNotify()办法就一向会被调用,但是实际上咱们并没有发布新的告诉,或许改动LiveData持有的目标,这个时分观察者就没必要被回调,所以经过一下代码进行拦截:

 if (observer.mLastVersion >= mVersion) {
            return;
        }

说白了LiveData中的观察者只有在数据发生改动之后才应该被回调,所以不论观察者的生命周期改动了多少次,只需数据没改动,就不需求进行回调。

到此,LiveData和Lifecycle的源码就差不多了。

假如你觉得这篇内容对你还蛮有协助,我想约请你帮我三个小忙: 点赞,转发,有你们的 『点赞和评论』,才是我发明的动力。微信搜索大众号 [小尘Android专栏] ,第一时间阅览更多干货知识!