Lifecycle实践和解析

2022-05-10 20:41:19 浏览数 (1)

Jetpack Lifecycle记录

在 Android 中,我们可以使用 JetpackLifecycle 组件来管理我们的生命周期,可以执行操作来响应另一个组件(例如 Activity )的生命周期变化。利用 Lifecycle ,我们可以写出非常精简和容易维护的代码。

关于 Lifecycle 的基础知识,再次不做重复描述,不了解的朋友可以直接参考官方文档:Lifecycle 。

我们关注一下如何实现自定义的 LifecycleOwner :

实现自己的 LifecycleRegistry

代码语言:javascript复制
lifecycleRegistry = LifecycleRegistry(this)

修改到自己的生命周期状态

代码语言:javascript复制
lifecycleRegistry.markState(Lifecycle.State.CREATED)

自己实现一个 LifecycleOwner

我们自己来实现一个 LifecyclerOwner ,假设一个场景,我们有非常复杂的UI布局,某些UI控件我们希望能动态的插拔在布局上,并且在拔下这个控件或者页面退出的时候,这个控件里面的资源可以自动释放。

image.png

我们先自定义我们需要动态插板的 View :

我们提供了一个 release 方法,代表生命周期走到 destroy 的时候,执行一些释放逻辑。

代码语言:javascript复制
class StubView : LinearLayout {
  
    fun release() {
        Log.d("StubView", "release")
    }

    init {
        val tv = TextView(context).apply {
            text= "占位控件"
            gravity = Gravity.CENTER
            setBackgroundColor(Color.BLUE)
            setTextColor(Color.WHITE)
        }
        this.addView(tv)
    }
}

既然我们需要 View 有自己的生命周期监听,那么我们需要自定义一个 LifecycleOwner :

代码语言:javascript复制
class LifecycleOwnerWrapper(owner: LifecycleOwner) : LifecycleOwner {

    private var lifecycleRegistry: LifecycleRegistry = LifecycleRegistry(owner)

    override fun getLifecycle(): Lifecycle {
        return lifecycleRegistry
    }

    fun markState(state: Lifecycle.State) {
        lifecycleRegistry.currentState = state
    }

    fun addObserver(ob: LifecycleObserver) {
        lifecycleRegistry.addObserver(ob)
    }

}

接着我们定义一个 ViewHolder 来表示ui 插拔的逻辑, installuninstall 方法分别代表装载和卸载这个控件:

代码语言:javascript复制
class StubViewHolder(val owner: Fragment, val binding: FragmentJetpackLifecycleBinding) {
    private var lifecycleOwner : LifecycleOwner = LifecycleOwnerWrapper(owner)

    fun addLifecycleObserver(ob: LifecycleObserver) {
        (lifecycleOwner as LifecycleOwnerWrapper).addObserver(ob)
    }

    fun install() {
        val stub = StubView(owner.context)
        (lifecycleOwner as LifecycleOwnerWrapper).markState(Lifecycle.State.STARTED)
        binding.stubContainer.addView(stub)
    }

    fun unInstall() {
        for (index in 0 until binding.stubContainer.childCount) {
            val child = binding.stubContainer[index]
            if (child is StubView) {
                (lifecycleOwner as LifecycleOwnerWrapper).markState(Lifecycle.State.DESTROYED)
                binding.stubContainer.removeView(child)
            }
        }
    }
}

在卸载的时候,把 LifecycleIwberWrapper 的状态标记成了 DESTROYED , 这时候我们在 Fragment 里面就可以绑定 Observer 去监听生命周期的变化:

代码语言:javascript复制
val stubVH = StubViewHolder(this, binding).apply {
            addLifecycleObserver(lifecycleOb)
        }

lifecycle.addObserver(lifecycleOb)

// 拔掉
stubVH.unInstall()

// 插入
stubVH.install()

然后定义我们的 LifecycleOb ,当生命周期的事件是 Event.ON_DESTROY 的时候,就会从容器里面找到这个 StubView ,然后在它被 remove 之前,执行它的 release 方法。

代码语言:javascript复制
val lifecycleOb = LifecycleEventObserver { source, event ->
            when (event) {
                Lifecycle.Event.ON_DESTROY -> {
                    // 销毁逻辑
                    for (index in 0 until binding.stubContainer.childCount) {
                        val child = binding.stubContainer[index]
                        if (child is StubView) {
                            child.release()
                        }
                    }
                }
            }
        }

到这里,我们就完成了一个自定义 LifecycleOwner 的例子,那么 Jetpack 是怎么实现 Lifecycle 的这一套逻辑的呢?我们从实现可以一探究竟

实现原理

我们来看下关键的 LifecycleRegistry 对象:

mObserverMap

FastSafeIterableMap<LifecycleObserver, ObserverWithState>

这是一个类似 LinekHashMap 的 map 对象,存储了我们添加的 LifecycleObserver 及状态,支持在迭代过程中对 map 进行修改。并且记录了 mStartmEnd

mAddingObserverCounter && mHandlingEvent

这两变量的作用基本一致,区分当前是否正在添加 Observer 或者处理生命周期事件。

moveToState

修改当前的状态

sync

状态不是已经同步的话,就一直执行while循环里面的逻辑去调整状态。如果当前状态小于最旧的observer的状态,那么状态是需要向后转换的,也就是 backwardPass ,如果当前状态大于最新的observer的状态,那么状态是需要向后转换的,也就是 forwardPass

例如 backwardPass

这个每个状态比当前状态小的 observer 都会执行 dispatchEvent 方法。这样就可以同步所有 Observer 的当前生命周期状态:

代码语言:javascript复制
void dispatchEvent(LifecycleOwner owner, Event event) {
    State newState = getStateAfter(event);
    mState = min(mState, newState);
    mLifecycleObserver.onStateChanged(owner, event);
    mState = newState;
}
绑定Observer 过程

大致的流程和结构如下图:

我们直接看 LifecycleRegistryaddObserver :

代码语言:javascript复制
@Override
public void addObserver(@NonNull LifecycleObserver observer) {
    State initialState = mState == DESTROYED ? DESTROYED : INITIALIZED;
    ObserverWithState statefulObserver = new ObserverWithState(observer, initialState);
	ObserverWithState previous = mObserverMap.putIfAbsent(observer, statefulObserver);
    
    
    LifecycleOwner lifecycleOwner = mLifecycleOwner.get();
    
    boolean isReentrance = mAddingObserverCounter != 0 || mHandlingEvent; // 判断是否是重入
    
    State targetState = calculateTargetState(observer);
    mAddingObserverCounter  ;
    
    while ((statefulObserver.mState.compareTo(targetState) < 0
                && mObserverMap.contains(observer))) {
    
        pushParentState(statefulObserver.mState);
        statefulObserver.dispatchEvent(lifecycleOwner, upEvent(statefulObserver.mState));
        popParentState();
        targetState = calculateTargetState(observer);
    }    
    
    if (!isReentrance) {
        sync();
    }
    
    mAddingObserverCounter--;
}

在添加生命周期监听的时候,首先会把 Observer 对象添加到 map 里面去。且生命周期是 INITIALIZED。 所以这时候需要调用 calculateTargetState 来计算正确的 state,并且 dispatch 下去。

isReentrance 则是用来判断是否是重入的,例如在 Observer 的回调里面又调用了 addObserver ,那么就是重入的了。只有在非重入的情况下,我们才需要进行同步的逻辑。否则就成了递归调用,没有必要。反正其他生命周期的操作也会对所有的 LifecycleObserver 进行同步。

同步状态

那么 sync 的时候到生命周期按照什么规则同步呢?在 forwardPassbackwardPass 里面,我们能看到 upEventdownEvent 的调用:

upEvent:

代码语言:javascript复制
private static Event upEvent(State state) {
        switch (state) {
            case INITIALIZED:
            case DESTROYED:
                return ON_CREATE;
            case CREATED:
                return ON_START;
            case STARTED:
                return ON_RESUME;
            case RESUMED:
                throw new IllegalArgumentException();
        }
        throw new IllegalArgumentException("Unexpected state value "   state);
    }

downEvent: _

代码语言:javascript复制
private static Event downEvent(State state) {
        switch (state) {
            case INITIALIZED:
                throw new IllegalArgumentException();
            case CREATED:
                return ON_DESTROY;
            case STARTED:
                return ON_STOP;
            case RESUMED:
                return ON_PAUSE;
            case DESTROYED:
                throw new IllegalArgumentException();
        }
        throw new IllegalArgumentException("Unexpected state value "   state);
    }

而最终的状态也会根据 getStateAfter 来得到:

getStateAfter: _

代码语言:javascript复制
static State getStateAfter(Event event) {
        switch (event) {
            case ON_CREATE:
            case ON_STOP:
                return CREATED;
            case ON_START:
            case ON_PAUSE:
                return STARTED;
            case ON_RESUME:
                return RESUMED;
            case ON_DESTROY:
                return DESTROYED;
            case ON_ANY:
                break;
        }
        throw new IllegalArgumentException("Unexpected event value "   event);
    }

这里非常的绕,直接读容易绕晕,我们整理一下:

downEvent

  • INITIALIZED -> 无
  • CREATED -> ON_DESTROY
  • STARTED -> ON_STOP
  • RESUMED -> ON_PAUSE
  • DESTROYED -> 无

upEvent

  • INITIALIZED -> ON_CREATE
  • DESTROYED -> ON_CREATE
  • CREATED -> ON_START
  • STARTED -> ON_RESUME
  • RESUMED -> 无

getStateAfter

  • ON_CREATE、ON_STOP -> CREATED
  • ON_START、ON_PAUSE -> STARTED
  • ON_RESUME -> RESUMED
  • ON_DESTROY -> DESTROYED

仔细看会发现这个其实就对应官网的那张 Lifecycle 的生命周期图:

image.png

回调

在更改状态的时候,会调用 moveToState 方法:

代码语言:javascript复制
private void moveToState(State next) {
        mState = next;
        mHandlingEvent = true;
        sync();
        mHandlingEvent = false;
}

这里仍然会在修改后同步状态。在 forward 和 backward 里都会调用

代码语言:javascript复制
observer.dispatchEvent(lifecycleOwner, event);
代码语言:javascript复制
void dispatchEvent(LifecycleOwner owner, Event event) {
	State newState = getStateAfter(event);
	mState = min(mState, newState);
	mLifecycleObserver.onStateChanged(owner, event);
	mState = newState;
}

这里就会回调我们的 LifecycleEventObserveronStateChanged 方法。

总结

Lifecycle 本身大大简化了生命周期相关的处理,非常有助于代码解耦。在 Jetpack 套件里面,其实也非常多的用到了 Lifecycle 。感兴趣的朋友也可以分享一下。

0 人点赞