Android jetpack 之 LiveData

首先,LiveData是什么
LiveData是一种可以被观察的数据存储器类,它可以感知其他组件(比如Activity,Fragment)的生命周期,并只更新处于活跃状态的组件. 当我们的应用组件处于 STARTEDRESUMED 状态,LiveData则会认为该组件处于活跃状态

开始使用LiveData,LiveData一般搭配ViewModel一起使用
首先我们会创建一个ViewModel,在ViewModel里面在创建LiveData,并提供getter方法进行访问.

class NameViewModel : ViewModel() {
    //LiveData是一个抽象类,一般使用它的 MutableLiveData 实现
    val currentName: MutableLiveData<String> by lazy {
        MutableLiveData<String>()
    }
}

接着在Activity的onCreate()方法中获取我们的NumViewModel (在依赖了Android KTX 中的 Fragment KTX模块后, 可以直接使用viewModels和activityViewModels属性委托绑定到ViewModel),接着为LiveDta注册观察者

override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)
    setContentView(R.layout.activity_main)
    //获取ViewModel对象
    val model = ViewModelProvider(this,
        ViewModelProvider.NewInstanceFactory()).get(NameViewModel::class.java)
    //创建观察者对象
    val nameObserver = Observer<String> { name ->
        //更新UI
    }
    //通过observe()来注册观察者
    model.currentName.observe(this, nameObserver)
}

在注册观察者之后系统会立即调用onChange()方法,来提供currentName中的最新值,如果LiveData对象尚未在currentName中设置值,则onChange()方法不会被调用.
现在已经创建了LiveData对象并且设置了观察者.我们只需要更新LiveData对象就可以完成对onChange()方法的调用.LiveData提了 setValue(T) 和 postValue(T) 两个方法来更新值,第一个用来在主线程上使用,第二个用来在工作线程上使用.

button.setOnClickListener {
    model.currentName.setValue("乌鸡哥")
}

LiveData 是怎么工作的
首先我们看下LiveData是如何注册一个观察者的

@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()方法的第一个参数是一个接口,提供了一个获取Lifecycle的方法,该对象可以对我们应用组件(如Activity,Fragment)的生命周期进行监听.LiveData能感知组件生命周期的能力就它带来的.  第二个参数就是我们的观察者对象.
从上面的代码可以看出.如果该观察者所在的组件已经销毁,则什么也不会做. 
紧接着,把我们传入的owner 和 observer 做了一个包装. 这个包装类实现了GenericLifecycleObserver这个接口.
然后把我们的观察者都存储到mObservers这个SafeIterableMap里.在这里做了一个判断,即一个观察者只能观察一个LiveData对象.
最后把我们的包装类和Lifecycle做了关联,这时我们的LiveData就获得了应用组件的生命周期感知能力.

那这个包装类是什么

class LifecycleBoundObserver extends ObserverWrapper implements GenericLifecycleObserver {
    @NonNull
    final LifecycleOwner mOwner;

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

    //判断该组件是否是活跃状态,大于等于STARTED时返回true
    @Override
    boolean shouldBeActive() {
        return mOwner.getLifecycle().getCurrentState().isAtLeast(STARTED);
    }

    //当组件的生命周期发生改变时调用
    @Override
    public void onStateChanged(LifecycleOwner source, Lifecycle.Event event) {
        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);
    }
}

.当观察者所在的组件生命周期发生改变后,会回调onStartChange,在里面会首先检查组件是不是已经销毁,销毁的话需要移除LiveData的观察者,还要移除包装类和Lifecycle的关联.

@MainThread
public void removeObserver(@NonNull final Observer<? super T> observer) {
    assertMainThread("removeObserver");
    ObserverWrapper removed = mObservers.remove(observer);
    if (removed == null) {
        return;
    }
    removed.detachObserver();
    removed.activeStateChanged(false);
}

在里面首先会从mObservers这个SafeIterableMap里面移除LiveData的观察者. 接着调用detachObserver移除包装类和Lifecycle的关联.最后调用activeStateChanged(false)

如果组件没有销毁,则会直接调用activeStateChanged(shouldBeActive())

void activeStateChanged(boolean newActive) {
    //如果状态没改变,什么也不做    
    if (newActive == mActive) {
        return;
    }
    // immediately set active state, so we'd never dispatch anything to inactive
    // owner
    //更新状态
    mActive = newActive;
    //当前LiveData没有任何活跃的观察者时为true
    boolean wasInactive = LiveData.this.mActiveCount == 0;
    LiveData.this.mActiveCount += mActive ? 1 : -1;
    if (wasInactive && mActive) {
        onActive();
    }
    if (LiveData.this.mActiveCount == 0 && !mActive) {
        onInactive();
    }
    if (mActive) {
        dispatchingValue(this);
    }
}

在里面就是判断了一下LiveData里面是否还有活跃的观察者.,从上面的代码看到,只有LiveData里面的活跃观察者从0变成1的时候才会调用onActive,并且只有活跃的观察者变成0的时候才会调用onInactive.最后判断了一个这个观察者是否是活跃的,如果是活跃的会调用dispatchingValue来向这一个观察者发送事件. 

使用setValue来通知观察者更新数据

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

 

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;
    //noinspection unchecked
    observer.mObserver.onChanged((T) mData);
}

在观察者调用onChanged方法之前,仍会有很多的判断.比如检查观察者是不是活跃的.是不是已经通知过了. 我们的LiveData里又一个mVersion.这个mVersion在每次的setValue操作后都会自增. 而我们的ObserverWapper 也会有一个mLastVersion.比较这两个值就可以确定我们的观察者是否已经回调了onChanged.

LiveData还有一个observeForever方法.只需传递一个观察者对象就好.使用这个方法来注册观察者会是LiveData失去生命周期感知能力.我们需要自己在合适的生命周期回调方法中移除观察者

扩展LiveData
我们可以扩展一个LiveData来监听一些服务

class MoneyLiveData : LiveData<BigDecimal>(){
    //金钱的管理类
    private val manager = MoneyManager()
    private val listener = { money: BigDecimal ->
        value = money
    }
    override fun onActive() {
        super.onActive()
        manager.registerListener(listener)
    }
    override fun onInactive() {
        super.onInactive()
        manager.removeListener(listener)
    }
}

这里包含一些重要的方法,onActive() 会在有活跃的观察者时调用, onInactive() 会在没有任何活跃的观察者时调用. setValue(T)会更新LiveData实例的值并将结果告知所有活跃的观察者,可以在Activity的onCreate()方法中使用

override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)
    setContentView(R.layout.activity_main)
    val moneyLiveData: MoneyLiveData = ...
    moneyLiveData.observe(this, Observer<BigDecimal> { money ->
        //更新UI
    })
}

转换LiveData
有时候我们会希望将LiveData对象分派给观察者之前改变里面存储的值,map(),又或者转换成别的LiveData对象,switchMap()

val oldLiveData: LiveData<String> = OldLiveData()
//使用 Transformations 的map() 来在对前一个LiveData的值进行修改
val newLiveData: LiveData<String> = Transformations.map(oldLiveData) {
    oldString -> "newString"
}
newLiveData.observe(this, Observer { Log.d("TAG", it)})

val oldLiveData: LiveData<String> = MutableLiveData<String>()
val newLiveData: LiveData<String> = MutableLiveData<String>()
//使用 Transformations 的switchMap()来对前一个LiveData转换为一个新的LiveData
val liveData = Transformations.switchMap(oldLiveData) { newLiveData}
liveData.observe(this, Observer { Log.d("TAG", it)})

 

上一篇:集群中名词解释


下一篇:使用JS监听DOM元素的属性及动画、CSS过渡