JetPack之LiveData源码纪要


LiveData的官方定义:LiveData是一种可以在给定生命周期内被观察的数据承载类。

1. 添加观察者的方式

有两种方式添加观察者:

  1. 通过observe(Observer)方法添加的观察者只有在生命周期拥有者活跃(处于STARTED或RESUMED状态)的时候才会接收到LiveData的修改通知,在生命周期拥有者进入DESTORUYED状态时会自动移除所有观察者。
  2. 通过observeForever(Observer)方法添加的观察者会一直接收到LiveData的修改通知,必须在适当时机调用removeObserver(Observer)。

1.1. observe(Observer)方式

observe(Observer)添加观察者的源码为:

public void observe(@NonNull LifecycleOwner owner, @NonNull Observer<? super T> observer) {
		//1.必须在主线程添加
        assertMainThread("observe");
        //2.在DESTROYED状态不允许添加
        if (owner.getLifecycle().getCurrentState() == DESTROYED) {
            return;
        }
        LifecycleBoundObserver wrapper = new LifecycleBoundObserver(owner, observer);
        ObserverWrapper existing = mObservers.putIfAbsent(observer, wrapper);
        //3. 不允许将相同的观察者添加给不同的生命周期拥有者
        if (existing != null && !existing.isAttachedTo(owner)) {
            throw new IllegalArgumentException("Cannot add the same observer"
                    + " with different lifecycles");
        }
        //4. 不重复添加生命周期观察者
        if (existing != null) {
            return;
        }
        owner.getLifecycle().addObserver(wrapper);
    }

该方式先将生命周期拥有者对象和观察者对象封装成一个LifecycleBoundObserver对象,该对象继承ObserverWrapper并实现LifecycleEventObserver,因此该对象即是LiveData观察者又是生命周期事件观察者,分别将该对象加入到LiveData观察者列表mObservers中和生命周期观察者列表中。通过JetPack之Lifecycle观察者的实现方式解读可以知道:当生命周期发生变化时生命周期事件观察者的onStateChanged()方法会被回调。下面看一下该方法:

class LifecycleBoundObserver extends ObserverWrapper implements LifecycleEventObserver {
        @NonNull
        final LifecycleOwner mOwner;
        
        @Override
        boolean shouldBeActive() {
            return mOwner.getLifecycle().getCurrentState().isAtLeast(STARTED);
        }

        @Override
        public void onStateChanged(@NonNull LifecycleOwner source,
                @NonNull Lifecycle.Event event) {
            //当接收到DESTROYED事件时会移除LiveData观察者
            if (mOwner.getLifecycle().getCurrentState() == DESTROYED) {
                removeObserver(mObserver);
                return;
            }
            activeStateChanged(shouldBeActive());
        }
    }

当有生命周期变化事件通知时,activeStateChanged(shouldBeActive())方法将会被调用,shouldBeActive()决定了是否通知LiveData观察者,注意shouldBeActive()方法中判断生命周期拥有者处于激活状态是当前状态大于等于STARTED枚举类型,这里RESUMED枚举类型是第一大,STARTED枚举类型是第二大。shouldBeActive()方法定义在虚类ObserverWrapper中:

private abstract class ObserverWrapper {
        final Observer<? super T> mObserver;
        boolean mActive;  //表示该Observer是否处于激活状态
        int mLastVersion = START_VERSION;

        void activeStateChanged(boolean newActive) {
        	//新激活状态与原激活状态相同时不通知观察者
            if (newActive == mActive) {
                return;
            }
            // immediately set active state, so we'd never dispatch anything to inactive
            // owner
            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);
            }
        }
    }

newActive是指当前生命周期拥有者的激活状态,LiveData观察者得到通知必须有两个条件:1.新状态与原状态不相同;2.必须处于激活状态。因此我们可以得到一下结论:
1.在Activity/Fragment中首次添加LiveData观察者,LiveData的初始值是会通知给观察者的;
2.在Activity/Fragment从后台切到前台时,会走onResume()回调,newActive、mActive均为true(只要大雨onStart的状态均为true)但是LiveData观察者不会接到通知。
3.当调用setValue()函数时,处于pause状态的LifeCyclerOwner会收到通知,这是因为当Fragment处于OnPause状态时会触发LifecycleRegistry更新其mState状态:

//LifecycleRegistry.java
//生命周期拥有者生命周期变化时会调用该函数
public void handleLifecycleEvent(@NonNull Lifecycle.Event event) {
    State next = getStateAfter(event); //对于PAUSE事件,则next = STARTED
    moveToState(next);
}

//LifecycleRegistry.java
static State getStateAfter(Event event) {
    switch (event) {
        case ON_CREATE:
        case ON_STOP:
            return CREATED;
        case ON_START:
        case ON_PAUSE:   //对于PAUSE事件,下一个状态被置为STARTED(State类型枚举)
            return STARTED;
        case ON_RESUME:
            return RESUMED;
        case ON_DESTROY:
            return DESTROYED;
        case ON_ANY:
            break;
    }
    throw new IllegalArgumentException("Unexpected event value " + event);
}

//LifecycleRegistry.java
private void moveToState(State next) {
    if (mState == next) {
        return;
    }
    //对于PAUSE事件,将mState置为STARTED
    mState = next;
    if (mHandlingEvent || mAddingObserverCounter != 0) {
        mNewEventOccurred = true;
        // we will figure out what to do on upper level.
        return;
    }
    mHandlingEvent = true;
    sync();
    mHandlingEvent = false;
}


//class LifecycleBoundObserver
boolean shouldBeActive() {
	//对于处于PAUSE状态的生命周期拥有者,mState = STARTED,这里返回true
    return mOwner.getLifecycle().getCurrentState().isAtLeast(STARTED);
}

1.2 observeForever(Observer)方法

observeForever(Observer)添加观察者的源码为:

 public void observeForever(@NonNull Observer<? super T> observer) {
 		//1.必须在主线程添加
        assertMainThread("observeForever");
        AlwaysActiveObserver wrapper = new AlwaysActiveObserver(observer);
        ObserverWrapper existing = mObservers.putIfAbsent(observer, wrapper);
		//2.不能将同一个Observer对象同时使用observe()方式添加和observeForever()方式添加
        if (existing instanceof LiveData.LifecycleBoundObserver) {
            throw new IllegalArgumentException("Cannot add the same observer"
                    + " with different lifecycles");
        }
        if (existing != null) {
            return;
        }
        //3.参数true表示通知观察者
        wrapper.activeStateChanged(true);
    }

该方式将观察者封装成一个AlwaysActiveObserver对象,并添加到观察者列表mObservers中去,并且该方式在添加一个观察者对象时会立即通知该观察者对象。

2. 观察者的通知方式

通过上一节的论述我们知道:不管是通过observe()方式还是observeForver()方式添加的观察者,首次添加时其对应LiveData观察者都会收到通知;不同的是:当LiveData发生变化时,前者的观察者必须在生命周期拥有者处于激活状态时才会收到通知,若生命周期处于非激活状态时LiveData发生变化,那么当生命周期拥有者重新恢复激活状态时会通知观察者,而后者不论生命周期拥有者处于激活与否LiveData观察者都会得到通知。观察者也分为两种:AlwayseActiveObserver和LifecycleBoundObserver。观察者的通知方式分为两种:

  1. 全局通知;
  2. 部分通知。

看一下具体的代码:

//LiveData.java
void dispatchingValue(@Nullable ObserverWrapper initiator) {
		//mDispatchingValue表示正在分发通知,mDispatchInvalidated表示是否无效分发。
		//当正在分发时又触发了一次分发操作,即会禁用当前分发,并通知前一次未完成的分发是无效的,前一次分发即会停止分发并重新分发所有通知。
		//所有操作都在主线程,这里的重入不会是多线程导致的,而是嵌套导致的
        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(); ) {
                    //该处是嵌套发生的地方,dispatchingValue()方法由setValue()方法引发调用,
                    //若在此处通知LiveData观察者,并在观察者的回调中继续调用setValue()方法机会产生嵌套。
                    //调用链为:dispatchingValue -> observer.onChanged -> setValue -> dispatchingValue
                    considerNotify(iterator.next().getValue());
                    //mDispatchInvalidated = true时跳出for循环,但是又会重新进入while循环
                    if (mDispatchInvalidated) {
                        break;
                    }
                }
            }
        } while (mDispatchInvalidated);
        mDispatchingValue = false;
    }

当initiator不为null时,前者只通知initiator这一个观察者,通知的场景是调用setValue()方法;若initiator为null时则通知mObservers中的所有观察者,通知的场景是调用observeForever()方法添加一个观察者或调用removeObserver移除一个观察者等。真正通知观察者的操作是在considerNotify()方法中进行的:

private void considerNotify(ObserverWrapper observer) {
		//如果observer的实际类型是LifecycleBoundObserver时,会在生命周期拥有者变为非激活状态时
		//通知该observer,并将其mActive设置为false,因此在这里就跳过该类observer
        if (!observer.mActive) {
            return;
        }
        //如果observer的实际类型是AlwayseActiveObserver时,其shouldBeActive()返回值恒为true,因此对于该类observer的mActive不会被设置为false
        if (!observer.shouldBeActive()) {
            observer.activeStateChanged(false);
            return;
        }
        //如果observer的版本号已经被更新为LiveData的最新版本号,不会通知观察者
        if (observer.mLastVersion >= mVersion) {
            return;
        }
        observer.mLastVersion = mVersion;
        observer.mObserver.onChanged((T) mData);
    }

通过setValue()时会触发更新所有观察者,在遍历过程中类型为LifecycleBoundObserver且其mActive为false的观察者得不到通知,类型为AlwayseActiveObserver的观察者将会一直收到通知。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
作为AI助手,我无法直接安装nvidia-jetpack,但是我可以为您提供一些步骤,帮助您完成源码安装nvidia-jetpack的过程。 1.下载nvidia-jetpack源码 您可以从官方网站下载nvidia-jetpack源码包,下载后解压到本地目录。 2.安装依赖包 在安装nvidia-jetpack前,您需要安装一些必要的依赖包,可以使用以下命令安装: ``` sudo apt-get update sudo apt-get install build-essential cmake git unzip pkg-config sudo apt-get install libjpeg-dev libpng-dev libtiff-dev sudo apt-get install libavcodec-dev libavformat-dev libswscale-dev libv4l-dev sudo apt-get install libxvidcore-dev libx264-dev sudo apt-get install libgtk-3-dev sudo apt-get install libatlas-base-dev gfortran ``` 3.安装CUDA 由于nvidia-jetpack需要CUDA支持,因此您需要先安装CUDA。您可以从nvidia官网下载相应的CUDA版本并按照官方指南进行安装。 4.安装cuDNN 同样,您需要安装cuDNN以支持nvidia-jetpack,您可以从nvidia官网下载相应的cuDNN版本并按照官方指南进行安装。 5.编译nvidia-jetpack 打开终端,进入nvidia-jetpack源码目录,执行以下命令: ``` mkdir build cd build cmake .. make -j4 ``` 其中-j4表示使用4个线程进行编译,可以根据您的CPU核心数进行调整。 6.安装nvidia-jetpack 编译成功后,执行以下命令进行安装: ``` sudo make install ``` 安装完成后,您可以执行以下命令进行验证: ``` jetson_release -v ``` 如果输出了正确的版本信息,则表示安装成功。 希望这些步骤能够帮助到您。请注意,由于nvidia-jetpack的安装过程较为复杂,如果您不熟悉Linux操作,请谨慎操作,以免造成不必要的损失。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值