美文网首页
Jetpack——LiveData使用及源码分析

Jetpack——LiveData使用及源码分析

作者: 刘孙猫咪 | 来源:发表于2021-04-14 21:22 被阅读0次

    添加依赖:

    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

    相关文章

      网友评论

          本文标题:Jetpack——LiveData使用及源码分析

          本文链接:https://www.haomeiwen.com/subject/xagllltx.html