zoukankan      html  css  js  c++  java
  • Jetpack学习-LiveData

    个人博客

    http://www.milovetingting.cn

    Jetpack学习-LiveData

    LiveData是什么

    LiveData是一种可观察的数据存储器类,具有生命周期的感知能力。

    简单使用

    LiveData一般都是和ViewModel一起使用。定义一个类继承自ViewModel:

    public class LiveDataSub extends ViewModel {
    
        private MutableLiveData<String> infos;
    
        private int number;
    
        public MutableLiveData<String> getInfo() {
            if (infos == null) {
                infos = new MutableLiveData<>();
            }
            return infos;
        }
    
        public int increaseNumber() {
            number++;
            return number;
        }
    }
    

    在这个类里定义MutableLiveData类型的属性,并提供外界访问的方法getInfo

    在Activity中使用

    public class LiveDataActivity extends AppCompatActivity {
    
        private TextView tv;
    
        private LiveDataSub viewModel;
    
        @Override
        protected void onCreate(@Nullable Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_livedata);
            tv = findViewById(R.id.tv);
            viewModel = ViewModelProviders.of(this).get(LiveDataSub.class);
            viewModel.getInfo().observe(this, new Observer<String>() {
                @Override
                public void onChanged(String s) {
                    tv.setText(s);
                }
            });
        }
    
        public void update(View view) {
            String info = "info:" + viewModel.increaseNumber();
            viewModel.getInfo().setValue(info);
        }
    }
    

    通过ViewModelProviders.of(this).get(LiveDataSub.class)来实例化刚才定义的ViewModel,然后通过调用LiveDataobserve方法添加对当前Activity的观察。

    通过LiveData的setValue可以来更新数据,此时界面会自动更新。

    原理

    从LiveData的observe方法来看

    添加observer

    @MainThread
        public void observe(@NonNull LifecycleOwner owner, @NonNull Observer<? super T> observer) {
            assertMainThread("observe");
            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);
        }
    

    observe方法的调用要求是在主线程。如果Activity对应的lifecycle已经处于DESTROYED状态,则会直接返回,不添加observer。最终还是调用了LifecycleaddObserver方法。

    数据更新

    数据更新,是通过LiveDatasetValue方法来执行的。

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

    这个方法要求在主线程上执行。方法内部调用了dispatchingValue方法

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

    由于之前传入的ObserverWrapper为null,因此会执行下面的迭代里的considerNotify方法

     private void considerNotify(ObserverWrapper 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.
            if (!observer.shouldBeActive()) {
                observer.activeStateChanged(false);
                return;
            }
            if (observer.mLastVersion >= mVersion) {
                return;
            }
            observer.mLastVersion = mVersion;
            //noinspection unchecked
            observer.mObserver.onChanged((T) mData);
        }
    

    在这个方法中,最终调用了observer的onChange方法。

    时序图:

    LiveData时序图.png

    数据异步更新

    上面的数据更新是在UI线程上执行的,如果想要在子线程上执行,那么则需要通过postValue方法。我们也来看一下这个方法

    protected void postValue(T value) {
            boolean postTask;
            synchronized (mDataLock) {
                //判断mPendingData是否已经赋值
                postTask = mPendingData == NOT_SET;
                //给mPendingData赋值
                mPendingData = value;
            }
            //如果已经赋值,则取消发送
            if (!postTask) {
                return;
            }
            ArchTaskExecutor.getInstance().postToMainThread(mPostValueRunnable);
        }
    

    这个方法是通过ArchTaskExecutor的postToMainThread方法来执行的。

    先看ArchTaskExecutor.getInstance()方法

    public static ArchTaskExecutor getInstance() {
            if (sInstance != null) {
                return sInstance;
            }
            synchronized (ArchTaskExecutor.class) {
                if (sInstance == null) {
                    sInstance = new ArchTaskExecutor();
                }
            }
            return sInstance;
        }
    

    再来看下构造方法

    private ArchTaskExecutor() {
            mDefaultTaskExecutor = new DefaultTaskExecutor();
            mDelegate = mDefaultTaskExecutor;
        }
    

    在这里实例化了mDefaultTaskExecutormDelegate

    调用postToMainThread方法

    @Override
        public void postToMainThread(Runnable runnable) {
            mDelegate.postToMainThread(runnable);
        }
    

    执行的是DefaultTaskExecutorpostToMainThread方法

    public void postToMainThread(Runnable runnable) {
            if (mMainHandler == null) {
                synchronized (mLock) {
                    if (mMainHandler == null) {
                        mMainHandler = new Handler(Looper.getMainLooper());
                    }
                }
            }
            //noinspection ConstantConditions
            mMainHandler.post(runnable);
        }
    

    可以看到,其实就是post了一个runnable到主线程中。

    private final Runnable mPostValueRunnable = new Runnable() {
            @Override
            public void run() {
                Object newValue;
                synchronized (mDataLock) {
                    //获取要更新的数据
                    newValue = mPendingData;
                    //mPendingData重置
                    mPendingData = NOT_SET;
                }
                //noinspection unchecked
                setValue((T) newValue);
            }
        };
    

    最终回调run方法里,还是调用的setValue方法。在run方法中,会获取要更新的数据,然后对mPendingData重置。因此,如果调用了多次postValue,如果前面的更新还没有处理,则并不会往主线程发送更新的消息,只会给mPendingData赋值,在run回调中,就会获取到最后一次的数据。

  • 相关阅读:
    Coursera机器学习week11 单元测试
    关于 TypeReference 的解释
    getModifiers 方法解释。
    instanceof isInstance isAssignableFrom 比较
    elasticsearch 基础 语法总结
    kibana 启动 关闭 和进程查找
    MD5 SHA1 SHA256 SHA512 SHA1WithRSA 的区别
    spring boot 项目 热启动
    java zip 压缩文件
    Packet for query is too large (1660 > 1024). You can change this value on the server by setting the max_allowed_packet' variable.
  • 原文地址:https://www.cnblogs.com/milovetingting/p/12701436.html
Copyright © 2011-2022 走看看