LiveData 的使用和原理

1. 简介

如果我们用过Rxjava 的话知道,Rxjava 是基于观察者模式实现的异步数据处理库,它可以在我们订阅的时候向我们分发数据,但有一点可惜的是Rxjava 的Observable 并不具备组件生命周期感知的能力,所以当我们在一个组件生命周期即将结束时取消订阅和数据分发时,需要手动去取消订阅;而谷歌官方退出的LiveData 恰恰解决了这个问题,LiveData 是一个数据持有者,同时它又具备了组件生命周期感知能力。当LiveData观察者处于非Active 状态时,LiveData不会将最新的变化通知给观察者。通常LiveData可以搭配ViewModel 一起使用,ViewModle 作为LiveData 的数据源,当数据更新后,LiveData会通知它的观察者。

2. 如何使用

LiveData 一般搭配ViewModel 使用,使用方式如下:

class MyViewModel: ViewModel() {

    #1 声明LiveData 
    val mutableLiveData = MutableLiveData()

}
lass MainActivity : AppCompatActivity() {
 
    private  lateinit var  myViewModel: MyViewModel
    private lateinit  var tv:TextView
    private lateinit var btnSetValue:Button
    private lateinit var btnPostValue:Button
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)
        #2 初始化ViewModel
        myViewModel= ViewModelProvider(this@MainActivity)[MyViewModel::class.java]
        tv = findViewById(R.id.tv1)
        btnSetValue = findViewById(R.id.btn_set_value)
        btnPostValue = findViewById(R.id.btn_post_value)
        

        #3 LiveData注册监听事件
        myViewModel.mutableLiveData.observe(this@MainActivity){
                tv.text= it
        }

        #4 调用LiveData setValue
        btnSetValue.setOnClickListener {
            myViewModel.mutableLiveData.value="this is value from set"
        }
        #5 调用LiveData postValue
        btnPostValue.setOnClickListener { 
            thread { 
                myViewModel.mutableLiveData.postValue("this is value from post")
            }
        }

}

#1.首先在ViewModel 中声明LiveData 变量,其中泛型决定了LiveData中持有数据的类型。

#2.在Activity 中 初始化ViewModel 对象。

#3. 给ViewModel 中的LiveData变量注册监听事件,当LiveData 的值发生变化时我们将值显示在TextView 上。

#4. 调用LiveData 的setValue ()方法,改变持有的数据值,并通知上面注册的观察者, 这个方法必须要在主线程中调用,否则会抛出异常。

#5. 调用LiveData 的 postValue() 方法,改变持有的数据值,并通知上面注册的观察者, 这个方法既可以在主线程调用也可以在子线程中调用。

LiveData 的使用和原理_第1张图片LiveData 的使用和原理_第2张图片

上面的图示分别表示执行#4 #5 后的效果。

2. LiveData原理

这里先从LiveData 的observer()方法开始:

  public void observe(@NonNull LifecycleOwner owner, @NonNull Observer observer) {
        #1 必须在主线程注册
        assertMainThread("observe");
        #2 这里查看LifecyclerOwner 的状态,如果是销毁状态,则返回
        if (owner.getLifecycle().getCurrentState() == DESTROYED) {
            // ignore
            return;
        }
        #3 将LifecycleOwner 和监听事件 封装为LifecycleBoundObserver 对象
        LifecycleBoundObserver wrapper = new LifecycleBoundObserver(owner, observer);

        #4 LifecycleBoundObserver 对象存在SafeIterableMap中
        ObserverWrapper existing = mObservers.putIfAbsent(observer, wrapper);

        #5 同一个监听事件不能绑定在不同的LifecycleOwner 上
        if (existing != null && !existing.isAttachedTo(owner)) {
            throw new IllegalArgumentException("Cannot add the same observer"
                    + " with different lifecycles");
        }
        if (existing != null) {
            return;
        }
        #6 将上面的wrapper 作为观察者添加到LifecycleOwner维护的观察者列表中,以此来绑定 
           LifecyclOwner的生命周期
        owner.getLifecycle().addObserver(wrapper);
    }

这里需要涉及到Lifecycle的一些知识,如果 不了解Lifecyle 可以自行了解下Lifecycle.  

#1. 主线程校验, LiveData注册监听事件必须在主线程中。

#2.如果当前所在的LifecycleOwner 也就是Activity 或者Fragment 已被销毁,则返回

#3. 将LifecycleOwner 和监听对象Observer 封装为LifecycleBoundObserver 对象, LifecycleBouondObserver 继承了ObserverWrapper 类并且实现了LifecycleEventObserver,所以它本质上是一个LifecycleOwner 生命周期的观察者, 当Activity 或者Fragment 生命周期发生变化时,会调用其内部重写的onStateChanged() 方法,改变其内部维护的Active 状态(可见为true, 不可见为false);当LiveData 的值发生变化时,会根据Active 状态决定是否下发改变的值。

#4 将LifecycleBoundObserver对象保存在观察者列表中

#5 同一个监听对象只能绑定在一个LifecycleOwner 上

#6 将LifecycleBoundObserver 对象添加到LifecycleOwner 维护的观察者列表中

总结一下:这个方法主要是将LiveData 监听对象Observer以及其所在的生命周期所有者LifecycleOwner(Activity 或者Fragment) 封装成LifecycleBoundObserver 对象并添加到 LiveData 维护的观察者列表中,随后将LifecycleBoundObserver 对象作为观察者注册到LifecycleOwner 维护的观察者列表中,这样当LifeycleOwner 也就是Activity 或者Fragment 生命周期发生变化时,LifecycleBoundObserver 的Active状态也会发生变化,当LiveData 的值发生改变时,会根据监听对象LifecycleBoundObserver所在的LifecycleOwner 的Active 状态是否活跃来确定是否要下发改变的值。

接着我们来看一下LifecycleBoundObserver 类

 #1 LiveData 的内部类,继承ObserverWrapper实现了LifecycleEventObserver, 所以他是Lifecyle 中的一个观察者
class LifecycleBoundObserver extends ObserverWrapper implements LifecycleEventObserver {
       
        #2 Activity、Fragment 或者自定义的具有生命的对象
        @NonNull
        final LifecycleOwner mOwner;

        LifecycleBoundObserver(@NonNull LifecycleOwner owner, Observer observer) {
            super(observer);
            mOwner = owner;
        }
        

        @Override
        boolean shouldBeActive() {
            return mOwner.getLifecycle().getCurrentState().isAtLeast(STARTED);
        }

         #3 LifecycleEventObserver 接口中的方法,LifecycleOwner 生命周期变化时调用
        @Override
        public void onStateChanged(@NonNull LifecycleOwner source,
                @NonNull Lifecycle.Event event) {
            #4 获取LifecycleOwner 的状态
            Lifecycle.State currentState = mOwner.getLifecycle().getCurrentState();
            #5 如果LifecycleOwner处于销毁状态,移除监听事件
            if (currentState == DESTROYED) {
                removeObserver(mObserver);
                return;
            }
            #6 改变状态并决定是否分发事件
            Lifecycle.State prevState = null;
            while (prevState != currentState) {
                prevState = currentState;
                activeStateChanged(shouldBeActive());
                currentState = mOwner.getLifecycle().getCurrentState();
            }
        }


         #7 ObserverWrapper 中的方法,为了方便我挪了出来
  void activeStateChanged(boolean newActive) {
            #8 活跃状态没有变化,返回
            if (newActive == mActive) {
                return;
            }
            // immediately set active state, so we'd never dispatch anything to inactive
            // owner
            mActive = newActive;
            changeActiveCounter(mActive ? 1 : -1);
            #9 处于活跃状态,下发值
            if (mActive) {
                dispatchingValue(this);
            }
        }
    }

这里主要看的是#3 当LifecycleOwner 生命周期发生变化时,调用onStateChanged() 方法,如果当前LifecycleOwner 状态是销毁状态,则移除监听事件;如果没有销毁,调用activeStateChanged() 方法来改变活跃状态,只有当LifecycleOwner 的状态至少是State.STARTED 时,mActive 为true 否则mActive 为false;如果新的状态同上次的状态相同,则什么都不做,如果不同,则判断当前状态mActive是否活跃,如果为true 则调用LiveData 的dispatchingValue()方法来下发值。

这块可能有点绕,如果了解Lifecycle 的状态就会好理解很多,Lifecycle中维护着生命周期的事件Event和状态State两个枚举,当某个生命周期事件执行完毕后,那么Lifecycle 就处于某个特定的状态State, 其对应关系如下:

Event            -------------------------->   State

ON_CREATE 

ON_STOP                                    CREATED

ON_START

ON_PAUSE                                  STARTED

ON_RESUME                               RESUMED

ON_DESTRORY                           DESTROYED              

可以看到当LifecycleOwner 状态为STARTED 或者RESUMED 的时候(对应的生命周期方法onStart(),onResume(),onPause()执行过后),mActive 才会为true, 否则mActive 为false。

这时候再看dispatchingValue() 方法

 void dispatchingValue(@Nullable ObserverWrapper initiator) {
        if (mDispatchingValue) {
            mDispatchInvalidated = true;
            return;
        }
        mDispatchingValue = true;
        do {
            mDispatchInvalidated = false;
           #1 如果initiator 不为null, 单独下发事件给这个监听事件
            if (initiator != null) {
                considerNotify(initiator);
                initiator = null;
            } else {
                
                 #2 遍历LiveData 维护的监听事件列表,并下发事件
                for (Iterator, ObserverWrapper>> iterator =
                        mObservers.iteratorWithAdditions(); iterator.hasNext(); ) {
                    considerNotify(iterator.next().getValue());
                    if (mDispatchInvalidated) {
                        break;
                    }
                }
            }
        } while (mDispatchInvalidated);
        mDispatchingValue = false;
    }

这里比较简单,#1当传入的具体的监听事件不为null 时,说明我们要单独下发给这个监听事件;#2 当传入的具体的监听事件为null 时,遍历LiveData 维护的监听事件列表并下发事件。

接着来到了considerNotify() 方法,

 private void considerNotify(ObserverWrapper observer) {
        #1 当前observer 状态mActive 为false 返回
        if (!observer.mActive) {
            return;
        }

        #2 再次检查observer 状态,如果为false,修改mActive
        if (!observer.shouldBeActive()) {
            observer.activeStateChanged(false);
            return;
        }
        if (observer.mLastVersion >= mVersion) {
            return;
        }
        observer.mLastVersion = mVersion;
        #3 调用observer 中维护的监听事件的onChanged()方法,也就是我们调用LiveData.observe(this) 
        {}方法的第二个参数
        observer.mObserver.onChanged((T) mData);
    }

这个方法中对当前ObserverWrapper 对象的活跃状态mAcive 进行检查,如果状态mActive 为false 则返回,否则调用我们注册监听事件时候传入的第二个参数Observer 对象的onChanged()方法,并传入需要下发的值。

以上是调用LiveData.observer() 方法后以及LifecycleOwner 生命周期变化时的执行流程。接着我们来看当我们主动调用LiveData.setValue() 或者LiveData.postValue() 的流程。

LiveData.setValue() :

 protected void setValue(T value) {
        #1 校验线程
        assertMainThread("setValue");
        mVersion++;
        mData = value;
        #2下发值
        dispatchingValue(null);
    }

可以看到非常简单,除了#1对主线程进行了校验外,就直接调用了dispatchingValue()方法,并且传入了null 作为参数,在上面我们说过当调用dispatchingValue()并传入null 时,会遍历LiveData 维护的监听对象然后下发值,这里就不再说明了。

LiveData.postValue() :

 protected void postValue(T value) {
        boolean postTask;
        synchronized (mDataLock) {
            postTask = mPendingData == NOT_SET;
            mPendingData = value;
        }
        if (!postTask) {
            return;
        }
       # 异步调用下发值
        ArchTaskExecutor.getInstance().postToMainThread(mPostValueRunnable);
    }
  private final Runnable mPostValueRunnable = new Runnable() {
        @SuppressWarnings("unchecked")
        @Override
        public void run() {
            Object newValue;
            synchronized (mDataLock) {
                newValue = mPendingData;
                mPendingData = NOT_SET;
            }
            setValue((T) newValue);
        }
    };

这里调用了ArchTaskExecutor 的postToMainThread() 方法,并将Runable 对象mPostValueRunable  当做参数传了进去,这里可以看到Runnable的run()方法也是直接调用了setValue()方法;

ArchTaskExecutor 是个线程管理工具类,它内部维护着一个线程数量为4的线程池 以及一个消息队列位于主线程的Handler 对象 mMainHandler

public class DefaultTaskExecutor extends TaskExecutor {

    private final Object mLock = new Object();

    private final ExecutorService mDiskIO = Executors.newFixedThreadPool(4, new ThreadFactory() {
        private static final String THREAD_NAME_STEM = "arch_disk_io_%d";

        private final AtomicInteger mThreadId = new AtomicInteger(0);

        @Override
        public Thread newThread(Runnable r) {
            Thread t = new Thread(r);
            t.setName(String.format(THREAD_NAME_STEM, mThreadId.getAndIncrement()));
            return t;
        }
    });

    @Nullable
    private volatile Handler mMainHandler;

    @Override
    public void executeOnDiskIO(Runnable runnable) {
        mDiskIO.execute(runnable);
    }

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

    @Override
    public boolean isMainThread() {
        return Looper.getMainLooper().getThread() == Thread.currentThread();
    }

    private static Handler createAsync(@NonNull Looper looper) {
        if (Build.VERSION.SDK_INT >= 28) {
            return Handler.createAsync(looper);
        }
        if (Build.VERSION.SDK_INT >= 16) {
            try {
                return Handler.class.getDeclaredConstructor(Looper.class, Handler.Callback.class,
                        boolean.class)
                        .newInstance(looper, null, true);
            } catch (IllegalAccessException ignored) {
            } catch (InstantiationException ignored) {
            } catch (NoSuchMethodException ignored) {
            } catch (InvocationTargetException e) {
                return new Handler(looper);
            }
        }
        return new Handler(looper);
    }
}

最终通过mMainHander.post() 方法,将mPostValueRunable 插入到主线程的消息队列中,最终还是调用了LiveData.setValue() 完成了值的下发。

到此,LiveData的分析就结束了。

你可能感兴趣的:(android)