天天看点

Android架构组件四 Android Architecture Components LiveData组件解析

1 前言

简单的说,LiveData是一个数据持有类,持有的数据可被观察者观察。它具有以下特点

  • 数据可以被观察者订阅;
  • 能够感知组件(Fragment、Activity、Service)的生命周期;
  • 只有在组件出于激活状态(STARTED、RESUMED)才会通知观察者有数据更新;

当然这里的组件都是指实现了LifecycleOwner接口的组件。

官方推荐我们使用LiveData时结合ViewModel来使用,从而达到解耦的目的。那么为什么需要使用LiveData呢?或者说,使用LiveData能给我们带来什么好处呢?

2 LiveData的功能

从官方文档来看,LiveData的使用有以下几大好处

  • 保证UI状态和数据的统一

LiveData采用了观察者设计模式。当生命周期状态改变时,LiveData会通知Observer对象。每次应用程序数据更改时,都会通知观察者对象,从而更新UI。

  • 减少内存泄漏

LiveData能够感知到组件的生命周期,观察者绑定到生命周期对象,并在其相关生命周期被破坏后自行清理。

  • 当Activity停止时不会引起崩溃

这是因为组件处于非激活状态时,不会收到LiveData中数据变化的通知

  • 不需要额外的手动处理来响应生命周期的变化

这一点同样是因为LiveData能够感知组件的生命周期,所以就完全不需要在代码中告诉LiveData组件的生命周期状态。

  • 组件和数据相关的内容能实时更新

组件在前台的时候能够实时收到数据改变的通知,这是可以理解的。当组件从后台到前台来时,LiveData能够将最新的数据通知组件,这两点就保证了组件中和数据相关的内容能够实时更新。

  • 针对configuration change时,不需要额外的处理来保存数据

我们知道,当你把数据存储在组件中时,当configuration change(比如语言、屏幕方向变化)时,组件会被recreate,然而系统并不能保证你的数据能够被恢复的。当我们采用LiveData保存数据时(结合ViewModel),因为数据和组件分离了。当组件被recreate,数据还是存在LiveData中,并不会被销毁。

  • 资源共享

通过继承LiveData类,然后将该类定义成单例模式,在该类封装监听一些系统属性变化,然后通知LiveData的观察者,例如下面的例子

/**
 * @author Created by qiyei2015 on 2018/2/25.
 * @version: 1.0
 * @email: [email protected]
 * @description: 监听网络是否连接的LiveData
 */
public class NetworkLiveData extends LiveData<Integer> {


    private static NetworkLiveData sNetworkLiveData;

    private WeakReference<Context> mContextWeakReference;

    private NetworkChangeReceiver mChangeReceiver;

    private NetworkLiveData(Context context){
        mContextWeakReference = new WeakReference<Context>(context);
    }

    /**
     * DCL 方式单例
     * @return
     */
    public static NetworkLiveData getInstance(Context context){
        if (sNetworkLiveData == null){
            synchronized (NetworkLiveData.class){
                if (sNetworkLiveData == null){
                    sNetworkLiveData = new NetworkLiveData(context);
                }
            }
        }
        return sNetworkLiveData;
    }

    /**
     * observer 从0 到1 调用
     */
    @Override
    protected void onActive() {
        super.onActive();
        IntentFilter filter = new IntentFilter(ConnectivityManager.CONNECTIVITY_ACTION);
        mChangeReceiver = new NetworkChangeReceiver();
        mContextWeakReference.get().registerReceiver(mChangeReceiver, filter);
    }

    /**
     * observer 从1 到0 调用
     */
    @Override
    protected void onInactive() {
        super.onInactive();
        mContextWeakReference.get().unregisterReceiver(mChangeReceiver);
    }

    /**
     * 网络状态变更的广播
     */
    private class NetworkChangeReceiver extends BroadcastReceiver {

        public final int wifi = , mobile = , none = ;
        public int oldState = none;

        /**
         * 触发网络状态监听回调
         *
         * @param nowStatus 当前网络状态
         */
        private void setChange(int nowStatus) {
            oldState = nowStatus;
            sNetworkLiveData.setValue(oldState);
        }

        @Override
        public void onReceive(Context context, Intent intent) {
            ConnectivityManager connectivityManager = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);
            NetworkInfo mobNetInfo = connectivityManager.getNetworkInfo(ConnectivityManager.TYPE_MOBILE);
            NetworkInfo wifiNetInfo = connectivityManager.getNetworkInfo(ConnectivityManager.TYPE_WIFI);
            if (!mobNetInfo.isConnected() && !wifiNetInfo.isConnected()) {
                Log.i("通知", "网络不可以用");
                setChange(none);
            } else if (mobNetInfo.isConnected()) {
                Log.i("通知", "仅移动网络可用");
                setChange(mobile);
            } else if (wifiNetInfo.isConnected()) {
                Log.i("通知", "Wifi网络可用");
                setChange(wifi);
            }
        }
    }


}
           

其中

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

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

这样子,在任何Activity/Fragment中我们都可以使用如下方式来观察网络状态变化

NetworkLiveData.getInstance(this).observe(this, new Observer<Integer>() {
            @Override
            public void onChanged(@Nullable Integer networkState) {
                //your code
            }
        });
           

注意,这里我们并没有显式在Activity/Fragment 中移除LiveData的监听,因为LiveData可以自动的帮我们处理这个过程

3 LiveData类图

LiveData的类图如下:

Android架构组件四 Android Architecture Components LiveData组件解析

可以看到,主要涉及到的类就是LiveData,MutableLiveData,LifecycleBoundObserver,Observer。其他的类已在LifeCycle中介绍过了。

我们先来看LiveData

LiveData< T >是一个抽象的泛型类,主要提供以下几个方法

@MainThread
public void observe(@NonNull LifecycleOwner owner, @NonNull Observer<T> observer)//添加观察者
@MainThread
public void observeForever(@NonNull Observer<T> observer)//添加永久的观察者,不考虑是否处于激活状态
@MainThread
public void removeObserver(@NonNull final Observer<T> observer)//移除观察者
@MainThread
public void removeObservers(@NonNull final LifecycleOwner owner)//移除被观察的对象
@Nullable
public T getValue()//获取持有的数据
public boolean hasObservers()//是否有观察者
public boolean hasActiveObservers()//是否有活跃的观察者
           

MutableLiveData

MutableLiveData继承自LiveData,源码如下,主要将postValue和setValue设置为Public。

public class MutableLiveData<T> extends LiveData<T> {
    @Override
    public void postValue(T value) {
        super.postValue(value);
    }

    @Override
    public void setValue(T value) {
        super.setValue(value);
    }
}
           

LifecycleBoundObserver

LifecycleBoundObserver是LiveData的内部类,实现于GenericLifecycleObserver接口,该接口又继承LifecycleObserver接口,主要用于LiveData添加观察者时,包装LifecycleOwner和Observer使用

class LifecycleBoundObserver implements GenericLifecycleObserver {
        public final LifecycleOwner owner;
        public final Observer<T> observer;
        public boolean active;
        public int lastVersion = START_VERSION;

        LifecycleBoundObserver(LifecycleOwner owner, Observer<T> observer) {
            this.owner = owner;
            this.observer = observer;
        }

        @Override
        public void onStateChanged(LifecycleOwner source, Lifecycle.Event event) {
            if (owner.getLifecycle().getCurrentState() == DESTROYED) {
                removeObserver(observer);
                return;
            }
            // immediately set active state, so we'd never dispatch anything to inactive
            // owner
            activeStateChanged(isActiveState(owner.getLifecycle().getCurrentState()));
        }

        void activeStateChanged(boolean newActive) {
            if (newActive == active) {
                return;
            }
            active = newActive;
            boolean wasInactive = LiveData.this.mActiveCount == ;
            LiveData.this.mActiveCount += active ?  : -;
            if (wasInactive && active) {
                onActive();
            }
            if (LiveData.this.mActiveCount ==  && !active) {
                onInactive();
            }
            if (active) {
                dispatchingValue(this);
            }
        }
    }
           

根据前面的分析,Activity/Fragment均实现了LifecycleOwner接口,并且当Activity/Fragment 生命周期变化时会发送相应的事件到LifecycleObserver的实例,因此,当Activity/Fragment生命周期变化时,最终会回调到LifecycleBoundObserver 的onStateChanged(LifecycleOwner source, Lifecycle.Event event)方法。关于这一点可以参考

Android架构组件二 Android Architecture Components Lifecycles 组件解析

4 LiveData解析

LiveData我觉得弄清楚以下几个问题就可以了。

1 LiveData如何添加观察者?

我们直接从observe(@NonNull LifecycleOwner owner, @NonNull Observer< T> observer)开始分析

@MainThread
    public void observe(@NonNull LifecycleOwner owner, @NonNull Observer<T> observer) {
        if (owner.getLifecycle().getCurrentState() == DESTROYED) {
            // ignore
            return;
        }
        LifecycleBoundObserver wrapper = new LifecycleBoundObserver(owner, observer);
        LifecycleBoundObserver existing = mObservers.putIfAbsent(observer, wrapper);
        if (existing != null && existing.owner != wrapper.owner) {
            throw new IllegalArgumentException("Cannot add the same observer"
                    + " with different lifecycles");
        }
        if (existing != null) {
            return;
        }
        owner.getLifecycle().addObserver(wrapper);
    }
           

首先根据LifecycleOwner 和Observer构造LifecycleBoundObserver 对象wrapper,然后将其添加到SafeIterableMap

实际上调用的是Activity/Fragment 中的LifecycleRegistry mLifecycleRegistry来添加观察者,最终会调用到LifecycleRegistry中的addObserver(@NonNull LifecycleObserver observer)

LifecycleRegistry.java

@Override
    public void addObserver(@NonNull LifecycleObserver observer) {
        State initialState = mState == DESTROYED ? DESTROYED : INITIALIZED;
        ObserverWithState statefulObserver = new ObserverWithState(observer, initialState);
        ObserverWithState previous = mObserverMap.putIfAbsent(observer, statefulObserver);

        if (previous != null) {
            return;
        }
        LifecycleOwner lifecycleOwner = mLifecycleOwner.get();
        if (lifecycleOwner == null) {
            // it is null we should be destroyed. Fallback quickly
            return;
        }

        boolean isReentrance = mAddingObserverCounter !=  || mHandlingEvent;
        State targetState = calculateTargetState(observer);
        mAddingObserverCounter++;
        while ((statefulObserver.mState.compareTo(targetState) < 
                && mObserverMap.contains(observer))) {
            pushParentState(statefulObserver.mState);
            statefulObserver.dispatchEvent(lifecycleOwner, upEvent(statefulObserver.mState));
            popParentState();
            // mState / subling may have been changed recalculate
            targetState = calculateTargetState(observer);
        }

        if (!isReentrance) {
            // we do sync only on the top level.
            sync();
        }
        mAddingObserverCounter--;
    }
           

这样,最终Activity/Fragment的生命周期变化会被LifecycleBoundObserver 观察到,这个和我们上面的分析一致。

同理LiveData的removeObserver(@NonNull final Observer< T> observer)逻辑也类似。最终会在LifecycleRegistry 中移除对Activity/Fragment的观察。

这样,添加和移除观察者的逻辑就理清楚了。

2 LiveData如何感知组件生命周期?

根据前面的分析,当LifecycleOwner的实现者Activity/Fragment 的生命周期变化,由于添加了LifecycleBoundObserver,因此最终会回调到LifecycleBoundObserver#onStateChanged(LifecycleOwner source, Lifecycle.Event event)方法

class LifecycleBoundObserver implements GenericLifecycleObserver {
        public final LifecycleOwner owner;
        public final Observer<T> observer;
        public boolean active;
        public int lastVersion = START_VERSION;

        LifecycleBoundObserver(LifecycleOwner owner, Observer<T> observer) {
            this.owner = owner;
            this.observer = observer;
        }

        @Override
        public void onStateChanged(LifecycleOwner source, Lifecycle.Event event) {
            if (owner.getLifecycle().getCurrentState() == DESTROYED) {
                removeObserver(observer);
                return;
            }
            // immediately set active state, so we'd never dispatch anything to inactive
            // owner
            activeStateChanged(isActiveState(owner.getLifecycle().getCurrentState()));
        }

        void activeStateChanged(boolean newActive) {
            if (newActive == active) {
                return;
            }
            active = newActive;
            boolean wasInactive = LiveData.this.mActiveCount == ;
            LiveData.this.mActiveCount += active ?  : -;
            if (wasInactive && active) {
                onActive();
            }
            if (LiveData.this.mActiveCount ==  && !active) {
                onInactive();
            }
            if (active) {
                dispatchingValue(this);
            }
        }
    }
           

可以看到onStateChanged(LifecycleOwner source, Lifecycle.Event event)的逻辑如下:

1 首先判断LifecycleOwner 的状态时候是DESTROYED,如果是直接移除观察者,这样就帮我们在LifecycleOwner 中移除了观察者,减少了很多重复性的代码

2 判断LifecycleOwner 的状态是否是Active,并根据mActiveCount Observer 的个数和Active状态开始回调onActive()或者onInactive()方法

3 如果activeStateChanged(boolean newActive)中判断到LifecycleOwner 的状态是Active,就调用dispatchingValue(this);进行数据的分发。最终会调用到LiveData的如下方法

private void considerNotify(LifecycleBoundObserver observer) {
        if (!observer.active) {
            return;
        }
        // Check latest state b4 dispatch. Maybe it changed state but we didn't get the event yet.
        //
        // we still first check observer.active to keep it as the entrance for events. So even if
        // the observer moved to an active state, if we've not received that event, we better not
        // notify for a more predictable notification order.
        if (!isActiveState(observer.owner.getLifecycle().getCurrentState())) {
            observer.activeStateChanged(false);
            return;
        }
        if (observer.lastVersion >= mVersion) {
            return;
        }
        observer.lastVersion = mVersion;
        //noinspection unchecked
        observer.observer.onChanged((T) mData);
    }
           

首先会判断LifecycleOwner是否处于前台,然后会调用

这样子会调用到Observer的onChanged(@Nullable T t)方法。

这样子就解释了为什么LifecycleOwner只有在前台才会收到数据更新。

有关LiveData的分析就暂时结束了,有关Android架构组件的分析也告一段落了,关于Room数据库组件暂时还没有用到。后续再写文章分析吧。

参考:

https://developer.android.google.cn/topic/libraries/architecture/livedata.html

https://shymanzhu.com/2017/12/23/Android%E6%9E%B6%E6%9E%84%E7%BB%84%E4%BB%B6%EF%BC%88%E4%BA%8C%EF%BC%89%E2%80%94%E2%80%94LiveData/#more