zgq105 / blog

2 stars 0 forks source link

关于androidx中的lifecycle原理解析 #97

Open zgq105 opened 2 years ago

zgq105 commented 2 years ago

1.lifecycle中是如何管理协程的生命周期?

看一个下面一个例子在AppCompatActivity中,用户点击按钮获取用户信息,但是网络请求还没回来,此时用户快速关闭页面,这个时候下面那段代码会有内存泄露风险吗?答案是不会,那它是怎么做到的呢?后面一一剖析。

private fun getUserInfo() {
        lifecycleScope.launch {
            //挂起发起网咯请求获取数据
            withContext(Dispatchers.IO) {
                //模拟耗时操作
                delay(30 * 1000)
            }
            //更新UI

        }
    }

lifecycleScope是ktx中的一个拓展属性,如下:

public val LifecycleOwner.lifecycleScope: LifecycleCoroutineScope
    get() = lifecycle.coroutineScope

同时,coroutineScope又是Lifecycle中的一个拓展属性,返回一个带有生命周期的协程作用域LifecycleCoroutineScope,如下:

public val Lifecycle.coroutineScope: LifecycleCoroutineScope
    get() {
        while (true) {
            val existing = mInternalScopeRef.get() as LifecycleCoroutineScopeImpl?
            if (existing != null) {
                return existing
            }
            val newScope = LifecycleCoroutineScopeImpl(
                this,
                SupervisorJob() + Dispatchers.Main.immediate
            )
            if (mInternalScopeRef.compareAndSet(null, newScope)) {
                newScope.register()
                return newScope
            }
        }
    }

这是使用了CAS机制保证LifecycleCoroutineScopeImpl类创建的线程安全,LifecycleCoroutineScopeImpl的类层次结构如下: LifecycleCoroutineScopeImpl -> LifecycleEventObserver -> LifecycleObserver,所以LifecycleCoroutineScopeImpl其实是一个观察者对象,注入的过程在newScope.register()方法,如下:

fun register() {
        launch(Dispatchers.Main.immediate) {
            if (lifecycle.currentState >= Lifecycle.State.INITIALIZED) {
                lifecycle.addObserver(this@LifecycleCoroutineScopeImpl)  //将观察者LifecycleCoroutineScopeImpl添加到Lifecycle中
            } else {
                coroutineContext.cancel()
            }
        }
    }

Lifecycle是一个抽象类,表示具有生命周期类的抽象,它的实现类是LifecycleRegistry,在内部实现了addObserver和removeObserver,观察者的存储是一个FastSafeIterableMap,如下:

private FastSafeIterableMap<LifecycleObserver, ObserverWithState> mObserverMap =
            new FastSafeIterableMap<>();

被观察者其实是一个LifecycleOwner接口,其实现类包括Fragment和ComponentActivity,以Activity为例,类的继承关系如下: MainActivity2(业务UI)-> AppCompatActivity -> FragmentActivity -> ComponentActivity -> LifecycleOwner

在FragmentActivity类中初始化了LifecycleRegistry,因此观察者LifecycleCoroutineScopeImpl和被观察者LifecycleOwner建立了关联,如下: private final LifecycleRegistry mFragmentLifecycleRegistry = new LifecycleRegistry(this);

所以,只要生命周期有变化,就会通知到观察者,如下所示:

image

看下这段代码其实就是把生命周期事件分发通知外部的观察者,如下:

public void handleLifecycleEvent(@NonNull Lifecycle.Event event) {
        enforceMainThreadIfNeeded("handleLifecycleEvent");
        moveToState(event.getTargetState());
    }

moveToState方法最终会调到sync()方法,如下:

private void moveToState(State next) {
    //.....
  sync();
  //.....
}

sync方法的调用如下:

private void sync() {
  LifecycleOwner lifecycleOwner = mLifecycleOwner.get(); //mLifecycleOwner在LifecycleRegistry中用于存储被观察者对象,使用弱引用实现
   //.....
   backwardPass(lifecycleOwner);
  //.....
  forwardPass(lifecycleOwner);
}

在backwardPass或者forwardPass方法中都是做遍历操作,挨个通知观察者,如下所示:

private void forwardPass(LifecycleOwner lifecycleOwner) {
        Iterator<Map.Entry<LifecycleObserver, ObserverWithState>> ascendingIterator =
                mObserverMap.iteratorWithAdditions();
        while (ascendingIterator.hasNext() && !mNewEventOccurred) {
            Map.Entry<LifecycleObserver, ObserverWithState> entry = ascendingIterator.next();
            ObserverWithState observer = entry.getValue();
            while ((observer.mState.compareTo(mState) < 0 && !mNewEventOccurred
                    && mObserverMap.contains(entry.getKey()))) {
                pushParentState(observer.mState);
                final Event event = Event.upFrom(observer.mState);
                if (event == null) {
                    throw new IllegalStateException("no event up from " + observer.mState);
                }
                observer.dispatchEvent(lifecycleOwner, event); //事件分发到外面
                popParentState();
            }
        }
    }

通过observer.dispatchEvent(lifecycleOwner, event); 最终调用到LifecycleCoroutineScopeImpl类中的onStateChanged方法,如下代码所示:

void dispatchEvent(LifecycleOwner owner, Event event) {
            State newState = event.getTargetState();
            mState = min(mState, newState);
            mLifecycleObserver.onStateChanged(owner, event); //调用LifecycleCoroutineScopeImpl中onStateChanged方法
            mState = newState;
        }

接着往下走,看看在LifecycleCoroutineScopeImpl中onStateChanged方法中做了什么,如下:

override fun onStateChanged(source: LifecycleOwner, event: Lifecycle.Event) {
        if (lifecycle.currentState <= Lifecycle.State.DESTROYED) {
            lifecycle.removeObserver(this)
            coroutineContext.cancel()
        }
    }

在这里收到销毁生命周期回调时,移除了协程观察者,保证了不会内存泄露。

2.lifecycle中是如何管理livedata的生命周期?

livedata注册观察者的过程,其实最终也是调用LifecycleRegistry来实现的原理和协程生命周期管理一个思路,如下:

public void observe(@NonNull LifecycleOwner owner, @NonNull Observer<? super T> observer) {
        //....
        LifecycleBoundObserver wrapper = new LifecycleBoundObserver(owner, observer);
        ObserverWrapper existing = mObservers.putIfAbsent(observer, wrapper); //保存观察者到集合中,便于数据变更发送通知
       //...
        owner.getLifecycle().addObserver(wrapper);//调用LifecycleRegistry类中的addObserver方法
    }

接下来看一下LifecycleBoundObserver的继承关系,如下: LifecycleBoundObserver -> ObserverWrapper -> LifecycleEventObserver -> LifecycleObserver 其实监听生命周期的回调是在LifecycleBoundObserver类中的onStateChanged方法,具体逻辑如下:

@Override
        public void onStateChanged(@NonNull LifecycleOwner source,
                @NonNull Lifecycle.Event event) {
            Lifecycle.State currentState = mOwner.getLifecycle().getCurrentState();
            if (currentState == DESTROYED) {
                removeObserver(mObserver); //ondestory的时候自动移除观察者
                return;
            }
            Lifecycle.State prevState = null;
            while (prevState != currentState) {
                prevState = currentState;
                activeStateChanged(shouldBeActive()); //其他生命周期的回调,更新livedata内部激活状态,非激活状态观察者一律收不到数据
                currentState = mOwner.getLifecycle().getCurrentState();
            }
        }