Jetpack——LiveData使用及源码分析

添加依赖:

implementation "android.arch.lifecycle:livedata:2.2.0"

在上一篇中简单的说了下ViewModel的使用和对源码简单分析了下,这里接着说LiveData的使用和源码分析。
google官网是这样描述LiveData的,LiveData是一种可观察的数据存储器类,和常规的可观察类不同,LiveData具有生命周期感知能力,意指它遵循其他应用组件(如Activity、Fragment或Service)的生命周期,这种感知能力可确保LiveData仅更新处于活跃生命周期状态的应用组件观察者。
通过上面的描述会得到一点:LivaData只会将更新通知给活跃的观察者,为观察LiveData对象而注册的非活跃观察者不会收到更改通知的。这样在activity或者fragment中使用时,就不必担心页面销毁时因无法释放而造成泄漏,系统会立即退订注册的观察者。

使用LiveData的优势:

确保界面符合数据状态

LiveData遵循观察者模式,当底层数据发生变化时,LiveData会通知Observer对象进行页面的更新;

不会发生内存泄漏

观察者会绑定到Lifecycle对象,并在其关联的生命周期遭到销毁后进行自我清理;

不会因activity的停止而导致崩溃

如果观察者的生命周期处于非活跃状态(如返回栈中的activity),则它不会接收任何LiveData事件;

不再需要手动处理生命周期

界面组件只是观察相关数据,不会停止或恢复观察,LiveData将自动管理所有这些操作,因为它在观察时可以感知相关的生命周期状态变化;

数据始终保持最新状态

如果生命周期变为非活跃状态,它会再次变为活跃状态时接收最新的数据;例如,曾经在后台的activity会在返回前台后立即接收最新的数据。

适当的配置更改

如果由于配置更改(如设备旋转)而重新创建了activity或者fragment,它会立即接收最新的可用数据;

共享资源

可以使用单例模式扩展LiveData对象以封装系统服务,以便在应用中共享它们;
LiveData既然有这么多优势,开发中必须的使用起来,在使用时,避免activity和fragment过于庞大,LiveData一般和ViewModel一起使用,activity和fragment负责页面数据的展示,LiveData和ViewModel负责数据的存储状态;

public class MyViewModel extends ViewModel {
    private static final String TAG = MyViewModel.class.getSimpleName();
    private MutableLiveData<String> currentName;

    public MutableLiveData<String> getCurrentName() {
        if (currentName == null) {
            currentName = new MutableLiveData<>();
        }
        return currentName;
    }

    @Override
    protected void onCleared() {
        super.onCleared();
        Log.d(TAG, "ViewModel has destory");
    }
}

LiveData是一个抽象类,MutableLiveData是系统提供的一个它的子类,一般使用的时候就用MutableLiveData;

public class ViewModelActivity extends BaseActivity {
    private static final String TAG = ViewModelActivity.class.getSimpleName();
    private ActivityViewmodelBinding binding;
    private MyViewModel myViewModel;

    @Override
    protected ViewBinding getViewBinding() {
        binding = ActivityViewmodelBinding.inflate(getLayoutInflater());
        return binding;
    }

    @Override
    protected void initData() {
        super.initData();
        //实例化ViewModel对象
        myViewModel = new ViewModelProvider(this).get(MyViewModel.class);
        myViewModel.getCurrentName().observe(this, new Observer<String>() {
            @Override
            public void onChanged(String s) {
                //进行更新ui或者其他逻辑
                Log.d(TAG, "s===" + s);
            }
        });
    }

    @Override
    protected void initView() {
        super.initView();
        binding.updateData.setOnClickListener(v -> {
            myViewModel.getCurrentName().setValue("数据刷新了");
        });
    }
}

在数据需要更新的时候调用setValue进行设置,然后会通过观察者通知,最终回调到onChanged的方法中,在onChanged方法中进行页面刷新或者其他逻辑即可;

@MainThread
    public void observe(@NonNull LifecycleOwner owner, @NonNull Observer<? super T> observer) {
        //检测当前添加观察者所处的线程,不能在background thread中使用
        assertMainThread("observe");
        //如果当前的生命周期是Destory就直接返回,不会进行观察者的注册
        if (owner.getLifecycle().getCurrentState() == DESTROYED) {
            // ignore
            return;
        }
        //将接收LiveData 的callback和Lifecycle生命周期进行绑定 将Observer变成有生命周期的LifecyleBoundObserver
        LifecycleBoundObserver wrapper = new LifecycleBoundObserver(owner, observer);
        //获取已经存在Observer 如果是每次都创建一个 existing肯定是null的
        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,这是一个拥有activity生命周期的接口,在ComponentActivity中就实现了该接口,Observer是一个接收LiveData的callback接口;看到会进行所在线程的检测,也就是LiveData不能在background thread中使用;在前面提到过LiveData只会对活跃状态的页面进行通知更新,非活跃状态的不会通知更新,如果是destory时,直接不会让注册观察者了;在LifecycleBoundObserver中通过Lifecycle生命周期的监听来管理Observer的移除,这样LiveData也就拥有的生命周期,同时也避免了因为页面的销毁而造成泄漏。

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() {
            //判断Observer是否处于活跃状态  getCurrentState 获取的是State
            //State是一个枚举 定义了DESTROYED INITIALIZED  CREATED STARTED RESUMED 这些Observer状态
            //而对于Observer处于STARTED 和RESUMED状态时 LiveData才会认为观察者处于活跃状态 这个时候才会将更新通知给到观察者
            return mOwner.getLifecycle().getCurrentState().isAtLeast(STARTED);
        }

        @Override
        public void onStateChanged(LifecycleOwner source, Lifecycle.Event event) {
            //活跃状态的监听回调
            if (mOwner.getLifecycle().getCurrentState() == DESTROYED) {
                //DESTROYED 时会移除掉注册的Observer
                removeObserver(mObserver);
                return;
            }
            //活跃状态的改变
            activeStateChanged(shouldBeActive());
        }

        @Override
        boolean isAttachedTo(LifecycleOwner owner) {
            //是否进行绑定
            return mOwner == owner;
        }

        @Override
        void detachObserver() {
           //解绑Observer 会直接移除对应的Observer
            mOwner.getLifecycle().removeObserver(this);
        }
    }

通过onStateChanged时时监听Observer的活跃状态,

void activeStateChanged(boolean newActive) {
            if (newActive == mActive) {
                //如果当前状态和之前一致 就不做处理
                return;
            }
            // immediately set active state, so we'd never dispatch anything to inactive
            // owner
            //更新observer状态
            mActive = newActive;
            //mActiveCount Observer活跃的次数
            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) {
                //处于活跃时LiveData通知Observer进行消息更新
                dispatchingValue(this);
            }
        }

如果Observer处于活跃状态时,会调用dispatchingValue进行消息更新,

void dispatchingValue(@Nullable ObserverWrapper initiator) {
        if (mDispatchingValue) {
            mDispatchInvalidated = true;
            return;
        }
        mDispatchingValue = true;
        do {
            mDispatchInvalidated = false;
            if (initiator != null) {
                //在添加Observer时 initiator是不为null 
                considerNotify(initiator);
                initiator = null;
            } else {
                //调用setValue方法重新设置时,initiator传入的是null
                for (Iterator<Map.Entry<Observer<? super T>, ObserverWrapper>> iterator =
                        mObservers.iteratorWithAdditions(); iterator.hasNext(); ) {
                    considerNotify(iterator.next().getValue());
                    if (mDispatchInvalidated) {
                        break;
                    }
                }
            }
        } while (mDispatchInvalidated);
        mDispatchingValue = false;
    }

不管initiator是不是null,最终都会调用considerNotify进行消息的刷新,

private void considerNotify(ObserverWrapper observer) {
    //Observer不是活跃状态直接返回
        if (!observer.mActive) {
            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.
    //再次检查Observer的状态 防止状态的改变
        if (!observer.shouldBeActive()) {
            observer.activeStateChanged(false);
            return;
        }
    //版本的判断
        if (observer.mLastVersion >= mVersion) {
            return;
        }
        observer.mLastVersion = mVersion;
        //noinspection unchecked
    //调用onChanged方法 将需要更新的消息回传回去
        observer.mObserver.onChanged((T) mData);
    }

到这里会看到最终调用了onChanged方法,也就是在上面activity中使用时重写的onChanged方法了,

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

会将Observer实例对象作为key,LifecycleBoundObserver实例对象作为value,缓存在双向链表结构的容器中,这样的目的就是在后面如果要使用到Observer时,直接从缓存中获取,就不需要进行重新注册,

public V putIfAbsent(@NonNull K key, @NonNull V v) {
    //通过observer对象实例key获取Entry实例
        Entry<K, V> entry = get(key);
        if (entry != null) {
            //如果存在就直接返回ObserverWrapper实例 在第一次时entry都是为null的,
            return entry.mValue;
        }
    //进行数据的保存
        put(key, v);
        return null;
    }
 protected Entry<K, V> put(@NonNull K key, @NonNull V v) {
     //创建Entry实例 Entry是一个双向链表结构的实体
        Entry<K, V> newEntry = new Entry<>(key, v);
        mSize++;
        if (mEnd == null) {
            mStart = newEntry;
            mEnd = mStart;
            return newEntry;
        }

        mEnd.mNext = newEntry;
        newEntry.mPrevious = mEnd;
        mEnd = newEntry;
        return newEntry;

    }

这里需要注意,第一次时ObserverWrapper实例肯定是null,要调用后面的addObserver添加观察者,后面继续调用oberver的话,ObserverWrapper实例存在并添加到当前的生命周期中时,不会注册新的观察者。找到Lifecycle子类LifecycleRegistry中的addObserver方法;

@Override
    public void addObserver(@NonNull LifecycleObserver observer) {
        //获取当前的状态
        State initialState = mState == DESTROYED ? DESTROYED : INITIALIZED;
        //将Observer和当前的状态进行绑定
        ObserverWithState statefulObserver = new ObserverWithState(observer, initialState);
        //将当前绑定状态的Observer保存在一个HashMap中
        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 != 0 || mHandlingEvent;
        //计算目前的活跃状态
        State targetState = calculateTargetState(observer);
        mAddingObserverCounter++;
        //判断是否为活跃状态 并且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);
        }

        if (!isReentrance) {
            // we do sync only on the top level.
            sync();
        }
        mAddingObserverCounter--;
    }
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;
        }
    }

这样就完成了活跃状态的监管,只需要更新活跃Observer消息即可,
观察者注册好后,调用setValue或者postValue后,在onChanged会调中就可以更新ui等操作了,

@MainThread
    protected void setValue(T value) {
        assertMainThread("setValue");
        mVersion++;
        mData = value;
        dispatchingValue(null);
    }

其实还是调用了dispatchingValue方法对需要更新的消息进行派发更新。

总结:

1、LiveData不能在background的线程中使用;
2、LiveData只会将更新通知给活跃的观察者,即处于STARTED或者RESUMED状态的Observer,非活跃状态的Observer不会收到更改通知;
3、对于注册的Observer会进行缓存,便于后面的使用,对于Observer采用匿名内部类的方式注册时,如果多次使用时需要注意会被多次注册,造成资源的浪费,可以将Observer的子类定义成全局的成员变量,这样保证每次传入的Observer始终是同一个,或者将Observer的注册放到onCreate中,只做数据改变的监听;
4、同一个Observer不能绑定多个不同的lifecycle
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 212,080评论 6 493
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,422评论 3 385
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 157,630评论 0 348
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,554评论 1 284
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 65,662评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,856评论 1 290
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,014评论 3 408
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,752评论 0 268
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,212评论 1 303
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,541评论 2 327
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,687评论 1 341
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,347评论 4 331
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,973评论 3 315
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,777评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,006评论 1 266
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,406评论 2 360
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,576评论 2 349

推荐阅读更多精彩内容