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回调中,就会获取到最后一次的数据。

  • 相关阅读:
    springboot + druid
    springboot + lombok
    springboot + swagger2
    Timer / TimerTask 源码解析
    Nginx(三) upstream目前支持的5种分配方式
    Nginx(一) 配置负载均衡
    Intellij IDEA 2018.02 激活方法
    Class常量池、String常量池、运行时常量池
    IntelliJ 结合 javap 实现class文件分析(反编译)
    关于登录注册的简单实现方式
  • 原文地址:https://www.cnblogs.com/milovetingting/p/12701436.html
Copyright © 2011-2022 走看看