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 currentName;

    public MutableLiveData 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() {
            @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 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 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, 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 entry = get(key);
        if (entry != null) {
            //如果存在就直接返回ObserverWrapper实例 在第一次时entry都是为null的,
            return entry.mValue;
        }
    //进行数据的保存
        put(key, v);
        return null;
    }
 protected Entry put(@NonNull K key, @NonNull V v) {
     //创建Entry实例 Entry是一个双向链表结构的实体
        Entry 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

你可能感兴趣的:(Jetpack——LiveData使用及源码分析)