Jetpack架构组件LiveData

基本使用

通常情况下Jetpack组件都是混合一起使用的,这里我们为了讲解,可能会单独使用。

这一篇我们来看一下liveData的使用,livedata特点如下:

  • LiveData是一个具有生命周期感知特性的可观察的数据保持类,使用LiveData保存数据时,在每次订阅或数据更新时会自动回调设置的观察者从而更新数据,真正的实现了数据驱动的效果。

  • LiveData的创建基本会在ViewModel中,从而使数据在界面销毁时继续保持。

  • LiveData 认为观察者的生命周期处于STARTED状态或RESUMED状态下,表示观察者处于活动状态,LiveData只通知活跃的观察者更新数据。

  • 注册一个实现该LifecycleOwner 接口的对象配对的观察者,当相应Lifecycle对象的状态改变为DESTROYED时移除观察者

一般LiveData通常跟ViewModel配合使用,也可以单独使用,为了简单起见,这里不配合 ViewModel。

public class LiveDataActivity extends AppCompatActivity {

    private TextView textView;
    private MutableLiveData<String> currentName;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_name);

        textView = findViewById(R.id.textView);
        
        currentName = new MutableLiveData<>();
        
        currentName.observe(this, new Observer<String>() {
            @Override
            public void onChanged(String s) {
                textView.setText(s);
            }
        });
        new Thread(){
            @Override
            public void run() {
                super.run();
                for(;;){
                    SystemClock.sleep(1000);
                    currentName.postValue(SystemClock.elapsedRealtime()+"");
                }
            }
        }.start();
    }
}

这里MutableLiveData是LiveData的一个子类,通过 observe 方法可以订阅修改数据的通知,通过 postValue() 或者 setValue() 方法可以更新数据,已经订阅的 Observer 能够得到数据更改的通知,也即回调 onChanged() 方法。

原理分析

使用超级简单,我们来分析LiveData原理。先从observe开始:

@MainThread
public void observe(@NonNull LifecycleOwner owner, @NonNull Observer<? super T> observer) {
    assertMainThread("observe");
    //如果是 DESTROYED 的状态则忽略
    if (owner.getLifecycle().getCurrentState() == DESTROYED) {
        // ignore
        return;
    }
    
    //把 Observer 用 LifecycleBoundObserver 封装起来
    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);
}

LifecycleBoundObserver

这里把observer包装成了LifecycleBoundObserver,并且和LifecycleOwner建立的关联。

LifecycleBoundObserver是抽象类ObserverWrapper子类,并且实现了LifecycleEventObserver接口,可以监听lifecycle的回调。在 onStateChanged() 方法里处理了生命周期改变的事件,当接收到 DESTROYED 的事件会自动解除跟 owner 的绑定,如果当前状态是active就将下个流程交给了 activeStateChanged() 。

class LifecycleBoundObserver extends ObserverWrapper implements LifecycleEventObserver {

    @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) {
        
        // 生命周期改变,如果是 DESTROYED 就自动解除
        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);
    }
}

activeStateChanged()

在 activeStateChanged() 方法里,处理了 onActive() 跟 onInactive() 回调的相关逻辑处理,并且调用了dispatchingValue(this)。

void activeStateChanged(boolean newActive) {

    //如果状态一样就返回
    if (newActive == mActive) {
        return;
    }
    mActive = newActive;
    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);
    }
}

dispatchingValue

如果使用的是setValue & postValue,那么ObserverWrapper则为空,会通知所有active的Observer。

如果是生命周期的改变,则不为空,只会通知跟该 Owner 绑定的 Observer。

void dispatchingValue(@Nullable ObserverWrapper initiator) {

    // 正在分发时则直接返回
    if (mDispatchingValue) {
        mDispatchInvalidated = true;
        return;
    }
    mDispatchingValue = true;
    do {
        mDispatchInvalidated = false;
        
        // 生命周期改变后会调用这里
        if (initiator != null) {
            considerNotify(initiator);
            initiator = null;
        } else {    // 使用setValue或者是postValue时执行这里
            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;
    }

    if (!observer.shouldBeActive()) {
        observer.activeStateChanged(false);
        return;
    }
    
    // 这里为了避免最经典的ABA问题,使用了版本控制
    if (observer.mLastVersion >= mVersion) {
        return;
    }
    observer.mLastVersion = mVersion;
    // 更新数据
    observer.mObserver.onChanged((T) mData);
}

总结

LiveData 基于观察者模式,并且可以感知生命周期,这使得我们使用 LiveData 既可以享受观察者模式带来的隔离数据与 UI 等强大的解耦能力,还可以享受感知生命周期带来的巨大便利。并且还无需担心内存泄露这个令人头疼的问题。

我们可以使用 LiveData 非常轻松地做到一些非常高效的操作,如仅在 active 的状态下刷新 UI,可以避免不必要的数据刷新。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值