美文网首页
Jetpack(二)LiveData

Jetpack(二)LiveData

作者: NIIIICO | 来源:发表于2022-04-24 17:12 被阅读0次

    LiveData是一种可被观察的数据存储器类。与常规的可观察类不同,LiveData可以观察生命周期,从而使它只有在组件处于活跃生命周期状态时通知观察者。

    一、使用

    LiveData对象通常存储在ViewModel对象中,并可通过getter方法进行访问,如以下示例中所示:

    1、创建LiveData对象
    public class NameViewModel extends ViewModel {
    
        // Create a LiveData with a String
        private MutableLiveData<String> currentName;
    
        public MutableLiveData<String> getCurrentName() {
            if (currentName == null) {
                currentName = new MutableLiveData<String>();
            }
            return currentName;
        }
    }
    
    2、添加观察者
    public class MainActivity extends AppCompatActivity {
        private NameViewModel model;
    
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_main);
    
            // 获取ViewModel
            model = new ViewModelProvider(this).get(NameViewModel.class);
            // 添加与生命周期有关的监听
            model.getCurrentName().observe(this, new Observer<String>() {
                @Override
                public void onChanged(@Nullable final String newName) {
                    // Update the UI, in this case, a TextView.
                    Log.v("AAAAA", "onChange newName:" + newName);
                }
            });
            // 添加与生命周期无关的监听
            model.getCurrentName().observeForever(new Observer<String>() {
                @Override
                public void onChanged(String newName) {
                    // Update the UI, in this case, a TextView.
                    Log.v("AAAAA", "observeForever onChange newName:" + newName);
                }
            });
        }
    
        public void onClick(View view) {
            // 改变liveData的值,主线程用set
            model.getCurrentName().setValue("LiMing set");
            // 改变liveData的值,子线程用post
            //model.getCurrentName().postValue("LiMing post");
        }
    }
    

    二、源码分析

    1、注册

    1.1、observe

    • (1)进行主线程判断
    • (2)判断组件的生命周期状态,如果被销毁,直接return
    • (3)包装组件和监听者,LifecycleBoundObserver实现了LifecycleEventObserver接口
    • (4)处理已经添加过的情况
    • (5)给组件添加生命周期监听
    public abstract class LiveData<T> {
        // 添加观察者
        public void observe(@NonNull LifecycleOwner owner, @NonNull Observer<? super T> observer) {
            // 确保是主线程
            assertMainThread("observe");
            // 获取组件的生命周期状态,如果已经销毁,直接return
            if (owner.getLifecycle().getCurrentState() == DESTROYED) {
                // ignore
                return;
            }
            // 包装组件和监听者
            LifecycleBoundObserver wrapper = new LifecycleBoundObserver(owner, observer);
    
            // 对于已经添加过的处理
            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);
        }
    }
    
    class LifecycleBoundObserver extends ObserverWrapper implements LifecycleEventObserver {}
    

    1.2、observeForever
    不同于observe,observeForever不需要关注组件的生命周期,因为缺少相关步骤。

    • (1)进行主线程判断
    • (2)包装监听者,AlwaysActiveObserver
    • (3)处理已经添加过的情况
    public abstract class LiveData<T> {
        @MainThread
        public void observeForever(@NonNull Observer<? super T> observer) {
            assertMainThread("observeForever");
            AlwaysActiveObserver wrapper = new AlwaysActiveObserver(observer);
            ObserverWrapper existing = mObservers.putIfAbsent(observer, wrapper);
            if (existing instanceof LiveData.LifecycleBoundObserver) {
                throw new IllegalArgumentException("Cannot add the same observer"
                        + " with different lifecycles");
            }
            if (existing != null) {
                return;
            }
            wrapper.activeStateChanged(true);
        }
    }
    
    2、通知

    2.1、修改内容

    public abstract class LiveData<T> {
        // 设置value
        protected void setValue(T value) {
            assertMainThread("setValue");
            mVersion++;
            mData = value;
            dispatchingValue(null);
        }
    
    
        private final Runnable mPostValueRunnable = new Runnable() {
            @SuppressWarnings("unchecked")
            @Override
            public void run() {
                Object newValue;
                synchronized (mDataLock) {
                    newValue = mPendingData;
                    mPendingData = NOT_SET;
                }
                setValue((T) newValue);
            }
        };
    
        // 子线程设置value,通过postValue,到主线程执行,最终还是调用setValue
        protected void postValue(T value) {
            boolean postTask;
            synchronized (mDataLock) {
                postTask = mPendingData == NOT_SET;
                mPendingData = value;
            }
            if (!postTask) {
                return;
            }
            ArchTaskExecutor.getInstance().postToMainThread(mPostValueRunnable);
        }
    }
    

    2.2、通知

    • setValue会调用到dispatchingValue方法,可以看到,传入的参数为null。
    • 由于参数为null,dispatchingValue方法走else,遍历mObservers所有包装好的监听者
    • considerNotify会判断组件的生命周期状态,看是否触发更新,然后调用onChanged
    public abstract class LiveData<T> {
        void dispatchingValue(@Nullable ObserverWrapper initiator) {
            if (mDispatchingValue) {
                mDispatchInvalidated = true;
                return;
            }
            mDispatchingValue = true;
            do {
                mDispatchInvalidated = false;
                if (initiator != null) {
                    considerNotify(initiator);
                    initiator = null;
                } else {
                    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;
    
            // 调用监听者的onChanged
            observer.mObserver.onChanged((T) mData);
        }
    }
    

    2.3、递归调用处理
    由2.2已经知道livedata的分发流程,它内部也对递归调用修改值做了处理;如下代码,最终打印结果为1、2、2。

    liveData.observeForever(new Observer<String>() {
        @Override
        public void onChanged(String s) {
            Log.v("AAAAA", "AAAAA:" + s);
            if ("1".equals(s)) {
                liveData.setValue("2");
            }
        }
    });
    
    liveData.observeForever(new Observer<String>() {
        @Override
        public void onChanged(String s) {
            Log.v("AAAAA", "AAAAA:" + s);
        }
    });
    
    liveData.setValue("1");
    

    下方为执行流程分析:

    1、首次setValue(1),进入dispatchingValue();
    2、if判断mDispatchingValue == false;不执行代码;
    3、mDispatchingValue = true,mDispatchInvalidated == false,进入do while;
    4、遍历观察者,通过considerNotify,回调onChanged方法;
    
    5、触发setValue(2),进入dispatchingValue();
    6、if判断mDispatchingValue == true,修改mDispatchInvalidated == true,return;
    7、回到considerNotify执行完毕,mDispatchInvalidated == true,触发break;
    8、由于mDispatchInvalidated == true触发while循环,走第二次分发流程,分发value == 2。
    
    3、粘性事件

    3.1、生命周期状态监听
    还有一种情况,当没有添加监听时,就设置value,之后再添加监听。包装类LifecycleBoundObserver可以监听组件生命周期,在生命周期变化时,会触发onStateChanged,最终通过dispatchingValue(this)进行分发。

    class LifecycleBoundObserver extends ObserverWrapper implements LifecycleEventObserver {
        public void onStateChanged(@NonNull LifecycleOwner source,
                @NonNull Lifecycle.Event event) {
            Lifecycle.State currentState = mOwner.getLifecycle().getCurrentState();
            // 当前状态为destroy,移除监听关系
            if (currentState == DESTROYED) {
                removeObserver(mObserver);
                return;
            }
    
            Lifecycle.State prevState = null;
            while (prevState != currentState) {
                prevState = currentState;
                // 当前为活跃状态,尝试同步数据
                activeStateChanged(shouldBeActive());
                currentState = mOwner.getLifecycle().getCurrentState();
            }
        }
    
        void activeStateChanged(boolean newActive) {
            if (newActive == mActive) {
                return;
            }
            // immediately set active state, so we'd never dispatch anything to inactive
            // owner
            mActive = newActive;
            changeActiveCounter(mActive ? 1 : -1);
            if (mActive) {
                dispatchingValue(this);
            }
        }
    }
    

    3.2、分发

    由于initiator不为null,直接走considerNotify进行分发。

    public abstract class LiveData<T> {
    void dispatchingValue(@Nullable ObserverWrapper initiator) {
            ...
            do {
                mDispatchInvalidated = false;
                if (initiator != null) {
                    considerNotify(initiator);
                    initiator = null;
                } else {
                    ...
                }
            } while (mDispatchInvalidated);
            mDispatchingValue = false;
        }
    }
    

    三、注意

    • 粘性事件只会响应最后一次的变化
    • 可以使用livedata做总线
    • 多线程情况下,高并发调用postValue,可能会只修改mPendingData的值,而把中间的某些值丢失。
    protected void postValue(T value) {
        boolean postTask;
        synchronized (mDataLock) {
            postTask = mPendingData == NOT_SET;
            mPendingData = value;
        }
        if (!postTask) {
            return;
        }
        ArchTaskExecutor.getInstance().postToMainThread(mPostValueRunnable);
    }
    

    相关文章

      网友评论

          本文标题:Jetpack(二)LiveData

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