目录
- 为什么使用Lifecycle?为什么不直接使用原生的activity的生命周期呢?
- Lifecycle是什么?
- 使用Lifecycle
- Lifecycle源码分析
一、为什么使用Lifecycle?为什么不直接使用原生的activity的生命周期呢?
我们想象一种场景,假如说你读取数据,开启了一个任务,那么结束的要关掉,那么就要写到onStop里面,但如果一个页面的任务多了,结束的代码都写到了onStop里面,那么就会冗余,一大堆的结束任务。并且移植性差,组件移植的话,还要去各个地方去复制,一不小心就漏了。
kotlin
override fun onStart() {
a.init()
b.start()
c.initialize()
...
}
...
override fun onStop(){
if(a!=null) a.remove()
if(b!=null&&b.c!=null) {
b.c.tearDown()
b.stop()
}
c.stop()
...
}
总结:
- 在
onCreate()
里启动网络请求,但页面关闭时未取消请求 → 内存泄漏 - 在
onStop()
后更新 UI → 崩溃 - 手动在多个生命周期方法中写重复逻辑 → 代码冗余
二、 Lifecycle是什么?
为了简化生命周期管理,Android Jetpack 提供了 Lifecycle
库,帮助开发者以更解耦的方式处理生命周期相关的逻辑。
- 核心概念:
-
LifecycleOwner
:具有生命周期的组件(如 Activity/Fragment 实现了此接口)。LifecycleObserver
:观察LifecycleOwner
的状态变化,并执行相应操作。
- 使用场景:
-
- 自动释放资源(如停止网络请求、注销监听器)。帮助开发者管理资源、避免内存泄漏,并确保应用的行为符合预期。
- 避免在后台执行不必要的任务(如更新 UI)。
三、使用
Android X已经帮助我们实现了这个接口LifecycleOwner。在AppcomActivity里面已经实现了监听。所以我们只需要实现观察者。
3.1 注解的方式
kotlin
class MyLifecycleObserver : LifecycleObserver {
@OnLifecycleEvent(Lifecycle.Event.ON_RESUME)
fun connectToNetwork() {
// 当 LifecycleOwner(如 Activity)进入前台时执行
}
@OnLifecycleEvent(Lifecycle.Event.ON_PAUSE)
fun disconnectFromNetwork() {
// 当 LifecycleOwner 进入后台时执行
}
}
// 在 Activity/Fragment 中注册观察者
lifecycle.addObserver(MyLifecycleObserver())
执行逻辑:
-
Activity 启动:
- 执行
onCreate()
→onStart()
→onResume()
。 - 当
onResume()
被调用时,LifecycleRegistry
检测到ON_RESUME
事件,触发观察者的connectToNetwork()
。
- 执行
-
Activity 进入后台:
- 用户按 Home 键 → 触发
onPause()
。 LifecycleRegistry
检测到ON_PAUSE
事件,调用disconnectFromNetwork()
。
- 用户按 Home 键 → 触发
-
Activity 销毁:
- 调用
onDestroy()
时,LifecycleRegistry
自动移除观察者,避免内存泄漏。
- 调用
但,注解都已经过时了。
废弃原因:
- 反射性能差:注解需要运行时解析,影响效率
- 代码可读性低:无法直接看出生命周期关联关系
- 编译期无校验:拼写错误或错误注解只在运行时崩溃
替代方案,上面也说了,实现 LifecycleEventObserver
或 DefaultLifecycleObserver
,接下来,我们看看DefaultLifecycleObserver
。
3.2 DefaultLifecycleObserver
java
class MyObserver implements DefaultLifecycleObserver {
@Override
public void onStart(@NonNull LifecycleOwner owner) {
// 明确关联到 onStart 生命周期
}
}
优势:
- 直接实现接口方法:无反射,性能更高
- 编译期检查:方法名错误会直接报错
- 代码更直观:IDE 自动提示关联的生命周期
四、源码分析
4.1 涉及的接口
java
LifecycleObserver接口
1. 注解:@OnLifecycleEvent(Lifecycle.Event.ON_STOP)
csharp
LifecycleOwner接口
1. 方法:Lifecycle getLifecycle();
markdown
Lifecycle抽象类
1. 方法:addObserver
4.2 从addObserver方法开始进入:为什么会他会调用我们实现了LifecycleObserver,加了注解的方法呢?
java
class MainActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
enableEdgeToEdge()
setContentView(R.layout.activity_main)
ViewCompat.setOnApplyWindowInsetsListener(findViewById(R.id.main)) { v, insets ->
val systemBars = insets.getInsets(WindowInsetsCompat.Type.systemBars())
v.setPadding(systemBars.left, systemBars.top, systemBars.right, systemBars.bottom)
insets
}
//进入主线流程
lifecycle.addObserver(object : LifecycleObserver {
})
}
}
java
@MainThread
public abstract void addObserver(@NonNull LifecycleObserver observer);
把LifecycleObserver 传递进来以后要做什么,没错,要做反射,反射,才能拿到里面的方法,可以看到,他都取出了getClass。
java
@Deprecated
class ReflectiveGenericLifecycleObserver implements LifecycleEventObserver {
private final Object mWrapped;
private final androidx.lifecycle.ClassesInfoCache.CallbackInfo mInfo;
@SuppressWarnings("deprecation")
ReflectiveGenericLifecycleObserver(Object wrapped) {
mWrapped = wrapped;
mInfo = ClassesInfoCache.sInstance.getInfo(mWrapped.getClass());
}
@Override
public void onStateChanged(@NonNull LifecycleOwner source, @NonNull Event event) {
mInfo.invokeCallbacks(source, event, mWrapped);
}
}
Object wrapped就是我们的LifecycleObserver,
ini
CallbackInfo getInfo(Class<?> klass) {
CallbackInfo existing = mCallbackMap.get(klass);
if (existing != null) {
return existing;
}
existing = createInfo(klass, null);
return existing;
}
使用map进行缓存。大部分的系统源码,都会搞缓存。第一次创建使用反射,第二次直接从缓存里面取。只要是反射都会搞缓存。避免消耗性能
4.3 LifecycleOwner的状态和事件
这里我们带着一个问题往下看看:为什么activity执行onstart会调用我们的方法,他是如何实现的呢?
java
public class ComponentActivity extends androidx.core.app.ComponentActivity implements
ContextAware,
LifecycleOwner,
.....
@OptIn(markerClass = BuildCompat.PrereleaseSdkCheck.class)
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
// Restore the Saved State first so that it is available to
// OnContextAvailableListener instances
mSavedStateRegistryController.performRestore(savedInstanceState);
mContextAwareHelper.dispatchOnContextAvailable(this);
super.onCreate(savedInstanceState);
ReportFragment.injectIfNeededIn(this);
if (BuildCompat.isAtLeastT()) {
mOnBackPressedDispatcher.setOnBackInvokedDispatcher(
Api33Impl.getOnBackInvokedDispatcher(this)
);
}
if (mContentLayoutId != 0) {
setContentView(mContentLayoutId);
}
}
我们看看ReportFragment.injectIfNeededIn(this)方法
Java
@JvmStatic
fun injectIfNeededIn(activity: Activity) {
if (Build.VERSION.SDK_INT >= 29) {
// On API 29+, we can register for the correct Lifecycle callbacks directly
LifecycleCallbacks.registerIn(activity)
}
// Prior to API 29 and to maintain compatibility with older versions of
// ProcessLifecycleOwner (which may not be updated when lifecycle-runtime is updated and
// need to support activities that don't extend from FragmentActivity from support lib),
// use a framework fragment to get the correct timing of Lifecycle events
val manager = activity.fragmentManager
if (manager.findFragmentByTag(REPORT_FRAGMENT_TAG) == null) {
manager.beginTransaction().add(ReportFragment(), REPORT_FRAGMENT_TAG).commit()
// Hopefully, we are the first to make a transaction.
manager.executePendingTransactions()
}
}
我们发现这里,为什么会有一个Fragment呢?因为我们都知道Activity执行生命周期的时候,如果Activity中有Fragment,那么Fragment也会执行相应的生命周期,所以他就这样来执行生命周期的。
我们来看看ReportFragment类的生命周期方法,果然会有
kotlin
override fun onActivityCreated(savedInstanceState: Bundle?) {
super.onActivityCreated(savedInstanceState)
dispatchCreate(processListener)
dispatch(Lifecycle.Event.ON_CREATE)
}
override fun onStart() {
super.onStart()
dispatchStart(processListener)
dispatch(Lifecycle.Event.ON_START)
}
我们看看dispatch方法
less
@Deprecated
class ReflectiveGenericLifecycleObserver implements LifecycleEventObserver {
private final Object mWrapped;
private final androidx.lifecycle.ClassesInfoCache.CallbackInfo mInfo;
@SuppressWarnings("deprecation")
ReflectiveGenericLifecycleObserver(Object wrapped) {
mWrapped = wrapped;
mInfo = ClassesInfoCache.sInstance.getInfo(mWrapped.getClass());
}
@Override
public void onStateChanged(@NonNull LifecycleOwner source, @NonNull Event event) {
mInfo.invokeCallbacks(source, event, mWrapped);
}
}
可以看到,最终,他取出反射对象,进行调用方法
csharp
void invokeCallback(LifecycleOwner source, Lifecycle.Event event, Object target) {
try {
switch (mCallType) {
case CALL_TYPE_NO_ARG:
mMethod.invoke(target);
break;
case CALL_TYPE_PROVIDER:
mMethod.invoke(target, source);
break;
case CALL_TYPE_PROVIDER_WITH_EVENT:
mMethod.invoke(target, source, event);
break;
}
} catch (InvocationTargetException e) {
throw new RuntimeException("Failed to call observer method", e.getCause());
} catch (IllegalAccessException e) {
throw new RuntimeException(e);
}
}
而且是循环遍历所有的观察的,因为我们可以添加多个观察者。
scss
while (statefulObserver.state < targetState && observerMap.contains(observer)
) {
pushParentState(statefulObserver.state)
val event = Event.upFrom(statefulObserver.state)
?: throw IllegalStateException("no event up from ${statefulObserver.state}")
statefulObserver.dispatchEvent(lifecycleOwner, event)
popParentState()
// mState / subling may have been changed recalculate
targetState = calculateTargetState(observer)
}
但前面我们会看到,有一个Lifecycle.Event.ON_CREATE,这是一个事件,前面我们用来注解的表标识,我们进去里面看,为什么会有一个State呢?有什么作用?
kotlin
public val targetState: State
get() {
when (this) {
ON_CREATE, ON_STOP -> return State.CREATED
ON_START, ON_PAUSE -> return State.STARTED
ON_RESUME -> return State.RESUMED
ON_DESTROY -> return State.DESTROYED
ON_ANY -> {}
}
throw IllegalArgumentException("$this has no target state")
}
4.4 状态机(State)与事件(Event)是什么?
- 状态(State) :表示组件当前的生命周期阶段,例如:
-
INITIALIZED
:刚初始化,未创建CREATED
:已创建(如Activity的onCreate
执行后)STARTED
:已启动(如Activity的onStart
执行后)RESUMED
:已恢复(如Activity的onResume
执行后)DESTROYED
:已销毁
- 事件(Event) :触发状态变化的操作,例如:
-
ON_CREATE
:对应onCreate()
方法ON_START
:对应onStart()
ON_RESUME
:对应onResume()
ON_PAUSE
:对应onPause()
ON_STOP
:对应onStop()
ON_DESTROY
:对应onDestroy()
为什么会出现两个事件,对应一个状态呢?
- 如果只用事件,当你想知道"当前是否在前台",只能通过记住最后一个事件(如
ON_RESUME
或ON_PAUSE
)来推断。 - 而状态(如
RESUMED
)直接告诉你"当前在前台",无需记忆历史事件。
当你知道是前台,还是后台,如果是后台,有些任务就不要执行,这样就可以减少资源消耗了。