一文读懂Jetpack LifeCycle的特性和实现

LifeCycle 生命周期

定义

Lifecycle是Jetpack架构组件中用来感知生命周期的组件,目标是使用Lifecycle可以帮助开发者写出与生命周期相关且更简洁、更易维护的代码(不将页面的生命周期透传给对应的组件)-- 监听者模式

使用方式

观察者:LifecycleObserver 和 LifecycleEventObserver

less 复制代码
//无接口,用注解的方式
public interface LifecycleObserver {
}
@OnLifecycleEvent(Lifecycle.Event.ON_DESTROY)


//使用接口的方式,无注解
public interface LifecycleEventObserver extends LifecycleObserver {
void onStateChanged(@NonNull LifecycleOwner source, @NonNull Lifecycle.Event event);
}

宿主:LifeCycleOwner

Fragment,Activity等默认实现了LifeCycleOwner,直接调用getLifeCycle就可以

这里主要讲的是自定义LifeCycleOwner

csharp 复制代码
//暴露的LifecycleOwner接口
public interface LifecycleOwner {
@NonNull
    Lifecycle getLifecycle();
}

//具体的view的实现过程
public Lifecycle getLifecycle() {
    return mLifecycleRegistry; //返回的是注册器
}

//本质这是一个注册器
LifecycleRegistry mLifecycleRegistry;
//注册器和LifeCycleOwner绑定,LifeCycleOwner通过注册器和Observer绑定
mLifecycleRegistry = new LifecycleRegistry(this); //对应的是LifeCycleOwner,但是是弱引用的关系,避免了内存泄漏
//手动更新对应的生命周期(在Activity和Fragment是在源码中实现的)
mLifecycleRegistry.handleLifecycleEvent(Lifecycle.Event.ON_START);

LifecycleRegistry允许手动设置生命周期通知观察者(使用场景是进行单测中手动更新状态)

绑定过程 :LifeCycleOwner绑定Observer

scss 复制代码
//在onCreate生命周期,需要在主线程
lifecycle.addObserver(fragmentLifecycleCallback)
//可以不需要removeObserver,因为在destroy的时候会自动清空

有默认实现LifecycleOwner的场景

  1. 需要首先在基础的地方有实现LifecycleOwner,下面的Activity默认实现了(FragmentActivity、AppCompatActivity以及Fragment都已经实现过了,可以直接使用)
scala 复制代码
public class ComponentActivity extends Activity implements LifecycleOwner
  1. 在基础类的地方增加注册
scss 复制代码
lifecycle.addObserver(advertisingManage)

应用场景

  1. 项目中一些通用的组件,不需要Activity每一个将生命周期都通知给它
  2. 在测试场景中可以通过LifeCycleRegistry mooc一些场景用于测试

优点

  1. 降低组件之间的耦合性,不需要逐层透传

缺点

  1. 灵活性强,不易维护:甚至可以自己既是一个Observer又是一个Owner
kotlin 复制代码
class FeedModel: LifecycleEventObserver, LifecycleOwner {
    constructor(feedRemoteSource: IFeedRemoteSource){
        lifecycleRegistry = LifecycleRegistry(this)
        lifecycleRegistry.currentState = Lifecycle.State.INITIALIZED
lifecycleRegistry.addObserver(this)
    }
    override fun getLifecycle(): Lifecycle {
        return lifecycleRegistry
    }    
}

实现方式

如何实现注册 & 解注册

  1. 在addObserver的时候会立即获得一次生命周期回调的,因为源码中的循环和sync
  2. 在removeObserver的时候不发送额外的销毁DESTROYED事件(避免引入更多的监听者复杂度),因为removeObserver会自动移除
scss 复制代码
public void addObserver(@NonNull LifecycleObserver observer) {
    //必须是主线程注册
    enforceMainThreadIfNeeded("addObserver");  
    
    //根据当前的状态生成一个Observer并更新到对应的状态
    State initialState = mState == DESTROYED ? DESTROYED : INITIALIZED;
    ObserverWithState statefulObserver = new ObserverWithState(observer, initialState);
    
    //将注册的监听器放在FastSafeIterableMap中,这个是LinkedHashMap的简版,允许在遍历的时候更改数据不发生crash(是创建了迭代副本,在遍历的时候按照副本进行遍历)
    ObserverWithState previous = mObserverMap.putIfAbsent(observer, statefulObserver);

    if (previous != null) {
        return;
    }
    LifecycleOwner lifecycleOwner = mLifecycleOwner.get();
    if (lifecycleOwner == null) {
        // it is null we should be destroyed. Fallback quickly
        return;
    }

    boolean isReentrance = mAddingObserverCounter != 0 || mHandlingEvent;
    State targetState = calculateTargetState(observer);
    mAddingObserverCounter++;
    
    //循环遍历上面的View全部状态(循环原因可以后面深究),但是明显
    while ((statefulObserver.mState.compareTo(targetState) < 0
            && mObserverMap.contains(observer))) {
        pushParentState(statefulObserver.mState);
        final Event event = Event.upFrom(statefulObserver.mState);
        if (event == null) {
            throw new IllegalStateException("no event up from " + statefulObserver.mState);
        }
        statefulObserver.dispatchEvent(lifecycleOwner, event);
        popParentState();
        // mState / subling may have been changed recalculate
        targetState = calculateTargetState(observer);
    }

    if (!isReentrance) {
        // we do sync only on the top level.
        sync();
    }
    mAddingObserverCounter--;
}

public void removeObserver(@NonNull LifecycleObserver observer) {
    enforceMainThreadIfNeeded("removeObserver");
    //不发送额外的
    mObserverMap.remove(observer);
}

LifeCycleOwner是如何实现的

Android 10以下Activity本质是通过ReportFragment感知Activity生命周期拦截的(ReportFragment在ComponentActivity中注入的)

scss 复制代码
protected void onCreate(@Nullable Bundle savedInstanceState)
    ReportFragment.injectIfNeededIn(this);
}

public static void injectIfNeededIn(Activity activity) {
    //Android 10以上直接注册生命周期回调
    if (Build.VERSION.SDK_INT >= 29) {
        LifecycleCallbacks.registerIn(activity);
    }
    
    android.app.FragmentManager manager = activity.getFragmentManager();
    if (manager.findFragmentByTag(REPORT_FRAGMENT_TAG) == null) {
        manager.beginTransaction().add(new ReportFragment(), REPORT_FRAGMENT_TAG).commit();
        //立即启动ReportFragment,以达到能够开始接收生命周期事件
        manager.executePendingTransactions();
    }
}

Fragment是通过LifeCycleRegistry实现的

javascript 复制代码
void performCreate(Bundle savedInstanceState) {
   //其中还通过LifeCycleOwner监听实现了:在OnStop生命周期的时候停止接受输入事件
   ....
   mLifecycleRegistry.handleLifecycleEvent(Lifecycle.Event.ON_CREATE);
}

为什么 Android 10 以上不再需要 ReportFragment?

  1. 能节省ReportFragment所占用的资源
  2. 能减少代码的复杂性
相关推荐
拉不拉了个多1 小时前
Compose UI 中万能的 Modifier
android·kotlin·android jetpack
daily_23333 小时前
c++领域展开第十五幕——STL(String类的模拟实现)超详细!!!!
android·开发语言·c++
m0_7482350713 小时前
【MySQL】数据库开发技术:内外连接与表的索引穿透深度解析
android·mysql·数据库开发
好易学·数据结构13 小时前
为什么要学习数据结构与算法
数据结构·算法·leetcode·面试·力扣·笔试·牛客网
Nicole Potter13 小时前
Lua如何实现面向对象的三大特性?
开发语言·游戏·面试·lua
WeiLai111213 小时前
面试基础--Spring Boot启动流程及源码实现
java·spring boot·分布式·后端·面试·架构
拉不动的猪14 小时前
刷刷题24
前端·javascript·面试
werch14 小时前
兼容移动端ios,安卓,web端底部软键盘弹出,输入框被遮挡问题
android·前端·ios
干饭高手15 小时前
面试150,数组 / 字符串
python·leetcode·面试
alexhilton15 小时前
不使用Jetpack Compose的10个理由
android·kotlin·android jetpack