美文网首页Android篇
LiveData基本使用和原理

LiveData基本使用和原理

作者: w达不溜w | 来源:发表于2021-03-07 16:51 被阅读0次

    LiveData是一个可以感知生命周期、可以被观察的数据容器,它可以存储数据,还会在数据发生改变时进行提醒。

    一、LiveData基本使用
    class NameViewModel : ViewModel() {
        //使用LiveData的子类MutableLiveData,包装String类型的数据
        private var current = MutableLiveData<String>()
    
        fun getCurrentName(): MutableLiveData<String> {
            return current
        }
    }
    
    class MainActivity : AppCompatActivity() {
        private lateinit var viewModel: NameViewModel
    
        override fun onCreate(savedInstanceState: Bundle?) {
            super.onCreate(savedInstanceState)
            setContentView(R.layout.activity_main)
    
            viewModel=ViewModelProvider(this).get(NameViewModel::class.java)
            //需要一个观察者观察数据
            val observer = Observer<String> {
                toast(it)
            }
            //订阅
            viewModel.getCurrentName().observe(this, observer)
        }
    
        //点击改变值
        fun changeData(view: View) {
            viewModel.getCurrentName().value = Random.nextInt(100).toString()
        }
    }
    

    LiveDataBus使用事件总线的方式:

    class LiveDataBus {
        //存放订阅者
        private var bus: HashMap<String, MutableLiveData<Any>> = HashMap()
    
        companion object {
            private val liveDataBus = LiveDataBus()
            fun getInstance() = liveDataBus
        }
        //注册订阅者
        @Synchronized
        fun <T> with(key: String, type: Class<T>): MutableLiveData<T> {
            if (!bus.containsKey(key)) {
                bus[key] = MutableLiveData()
            }
            return bus[key] as MutableLiveData<T>
        }
    }
    

    注册订阅:

    LiveDataBus.getInstance().with("data",String::class.java)
        .observe(this, Observer {
           toast(it.toString())
        })
    

    发送消息:

    LiveDataBus.getInstance().with("data", String::class.java).value="发送消息"
    
    二、LiveData原理分析

    observe方法:

    @MainThread
    public void observe(@NonNull LifecycleOwner owner, @NonNull Observer<? super T> observer) {
        assertMainThread("observe");
        //如果销毁状态,直接返回
        if (owner.getLifecycle().getCurrentState() == DESTROYED) {
            // ignore
            return;
        }
       //用LifecycleBoundObserver包装传进来的owner和observer
        LifecycleBoundObserver wrapper = new LifecycleBoundObserver(owner, observer);
       //缓存到mObservers集合中
        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);
    }
    

    LifecycleBoundObserver
    当Activity或Fragment生命周期发生改变时,会调用LifecycleBoundObserver中的onStateChanged方法,onStateChanged会调用observer中的onChanged

    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() {
            return mOwner.getLifecycle().getCurrentState().isAtLeast(STARTED);
        }
    
        @Override
        public void onStateChanged(LifecycleOwner source, Lifecycle.Event event) {
           //这里会判断owner的状态,如果是DESTROYED状态,移除观察者,这就是我们不需要手动remove oberver
            if (mOwner.getLifecycle().getCurrentState() == DESTROYED) {
                removeObserver(mObserver);
                return;
            }
            activeStateChanged(shouldBeActive());
        }
    
        @Override
        boolean isAttachedTo(LifecycleOwner owner) {
            return mOwner == owner;
        }
    
        @Override
        void detachObserver() {
            mOwner.getLifecycle().removeObserver(this);
        }
    }
    

    接着从setValue入手(子线程用postValue,会切换到主线程执行setValue进行消息传递,主线程直接用setValue)

    @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 {
              //setValue时initiator为null走这里
              //遍历mObservers(上面缓存owner和observer的集合)
                for (Iterator<Map.Entry<Observer<? super T>, ObserverWrapper>> iterator =
                        mObservers.iteratorWithAdditions(); iterator.hasNext(); ) {
                    considerNotify(iterator.next().getValue());
                    if (mDispatchInvalidated) {
                        break;
                    }
                }
            }
        } while (mDispatchInvalidated);
        mDispatchingValue = false;
    }
    

    进入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.
      
       //shouldBeActive返回mOwner.getLifecycle().getCurrentState().isAtLeast(STARTED),即STARTED及以后的状态
        if (!observer.shouldBeActive()) {
           //观察者如果不是STARTED、RESUMED,就把mActive的状态改为false
            observer.activeStateChanged(false);
            return;
        }
        //走到这说明Activity已经处于可见状态
        if (observer.mLastVersion >= mVersion) {
            return;
        }
        observer.mLastVersion = mVersion;
        //回调onChanged
        observer.mObserver.onChanged((T) mData);
    }
    
    三、小结

    对于LiveData,其初始化version是-1,当我们调用其setValue或postValue,其version会+1;对于每一个观察者的封装ObserverWrapper,其初始值version也为-1,当LiveData设置ObserverWrapper时,如果LiveData的version大于ObserverWrapper的version,回同步version,并且LiveData会把当前value推给Observer。


    LiveData.png
    问题出现

    由于粘性机制会使得订阅者会收到订阅之前发送的消息。
    解决办法就是让 第一个setValue失效,反射mLastVersion和mVersion让它们相等,就不会回调onChanged。

    //非粘性LiveData
    class LiveDataBus {
        //存放订阅者
        private var bus: HashMap<String, BusMutableLiveData<Any>> = HashMap()
    
        companion object {
            private val liveDataBus = LiveDataBus()
            fun getInstance() = liveDataBus
        }
    
        //注册订阅者
        @Synchronized
        fun <T> with(key: String, type: Class<T>): MutableLiveData<T> {
            if (!bus.containsKey(key)) {
                bus[key] = BusMutableLiveData()
            }
            return bus[key] as MutableLiveData<T>
        }
    
        inner class BusMutableLiveData<T> : MutableLiveData<T>() {
            override fun observe(owner: LifecycleOwner, observer: Observer<in T>) {
                super.observe(owner, observer)
                try {
                    hook(observer)
                } catch (e: Exception) {
                    e.printStackTrace()
                }
            }
    
             @Throws(java.lang.Exception::class)
             private fun hook(@NonNull observer: Observer<in T>) {
                 //get wrapper's version
                 val classLiveData = LiveData::class.java
                 val fieldObservers = classLiveData.getDeclaredField("mObservers")
                 fieldObservers.isAccessible = true
                 val objectObservers = fieldObservers[this]
                 val classObservers: Class<*> = objectObservers.javaClass
                 val methodGet = classObservers.getDeclaredMethod("get", Any::class.java)
                 methodGet.isAccessible = true
                 val objectWrapperEntry = methodGet.invoke(objectObservers, observer)
                 var objectWrapper: Any? = null
                 if (objectWrapperEntry is Map.Entry<*, *>) {
                     objectWrapper = objectWrapperEntry.value
                 }
                 if (objectWrapper == null) {
                     throw NullPointerException("Wrapper can not be bull!")
                 }
                 val classObserverWrapper: Class<*> = objectWrapper.javaClass.superclass
                 val fieldLastVersion = classObserverWrapper.getDeclaredField("mLastVersion")
                 fieldLastVersion.isAccessible = true
                 //get livedata's version
                 val fieldVersion = classLiveData.getDeclaredField("mVersion")
                 fieldVersion.isAccessible = true
                 val objectVersion = fieldVersion[this]
                 //set wrapper's version
                 fieldLastVersion[objectWrapper] = objectVersion
             }
    
        }
    }
    

    相关文章

      网友评论

        本文标题:LiveData基本使用和原理

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