第3章:创建自定义LifecycleOwner类:继承接口、成员变量、LifecycleRegistry初始化
自定义LifecycleOwner是Android生命周期管理扩展的核心步骤。本章系统讲解如何通过继承接口、声明成员变量、初始化LifecycleRegistry来构建一个标准、可复用的自定义LifecycleOwner。
3.1 接口继承与契约
所有LifecycleOwner必须实现单一接口:androidx.lifecycle.LifecycleOwner,该接口仅声明一个方法getLifecycle(),返回当前组件的生命周期状态。契约要求:返回的Lifecycle对象必须真实反映组件的生命周期变化,不能返回静态或虚假状态。
public interface LifecycleOwner {
@NonNull
Lifecycle getLifecycle();
}
3.2 成员变量:LifecycleRegistry
LifecycleRegistry是Lifecycle的标准实现,负责状态管理、观察者通知和线程安全。
- 职责:维护当前状态、注册/注销观察者、触发状态转移事件。
- 生命周期:通常与自定义Owner同生共死,在Owner销毁时清理。
- 线程安全:内部使用
FastSafeIterableMap和锁机制,支持多线程调用。
public class MyCustomOwner implements LifecycleOwner {
private final LifecycleRegistry lifecycleRegistry;
public MyCustomOwner() {
lifecycleRegistry = new LifecycleRegistry(this);
}
@NonNull
@Override
public Lifecycle getLifecycle() {
return lifecycleRegistry;
}
}
3.3 初始化流程
完整的初始化包含三个步骤:构造注册表、设置初始状态、启动生命周期观察。
- 在构造函数中创建
LifecycleRegistry(this)。 - 调用
lifecycleRegistry.setCurrentState(State.INITIALIZED)设置初始状态。 - 在适当位置(如
onStart回调)调用lifecycleRegistry.setCurrentState(State.STARTED)或handleLifecycleEvent(Event.ON_START)。
public class TimerLifecycleOwner implements LifecycleOwner {
private final LifecycleRegistry lifecycleRegistry = new LifecycleRegistry(this);
public TimerLifecycleOwner() {
lifecycleRegistry.setCurrentState(State.INITIALIZED);
}
public void start() {
lifecycleRegistry.setCurrentState(State.STARTED);
lifecycleRegistry.setCurrentState(Event.ON_START); // 推荐方式
}
public void stop() {
lifecycleRegistry.setCurrentState(State.CREATED); // 直接降级
lifecycleRegistry.handleLifecycleEvent(Event.ON_STOP); // 或使用事件
}
@NonNull
@Override
public Lifecycle getLifecycle() {
return lifecycleRegistry;
}
}
🔥 关键原则:每次状态变化必须通过
setCurrentState()或handleLifecycleEvent()完成,禁止直接修改内部mState字段。推荐使用事件驱动方式,更符合标准生命周期模型。3.4 调试与验证
使用LifecycleRegistry的addObserver方法注册调试观察者,打印状态变化日志。
public class DebugObserver implements DefaultLifecycleObserver {
private static final String TAG = "LifecycleDebug";
@Override
public void onCreate(LifecycleOwner owner) {
Log.d(TAG, "State: " + owner.getLifecycle().getCurrentState());
}
// 其他回调同理
}
| 状态转移 | 常用方式 | 副作用 |
|---|---|---|
| INITIALIZED → CREATED | setCurrentState(CREATED) | 触发ON_CREATE事件 |
| CREATED → STARTED | handleLifecycleEvent(ON_START) | 自动计算状态 |
| STARTED → RESUMED | handleLifecycleEvent(ON_RESUME) | 触发ON_RESUME |
| RESUMED → STARTED | handleLifecycleEvent(ON_PAUSE) | 自动降级 |
| STARTED → CREATED | handleLifecycleEvent(ON_STOP) | 触发ON_STOP |
| CREATED → DESTROYED | setCurrentState(DESTROYED) | 触发ON_DESTROY,清理 |
3.5 常见错误与对策
- 忘记设初始状态:
getCurrentState()默认INITIALIZED,但不调用setCurrentState(INITIALIZED)可能造成观察者在Owner未完全初始化时收到事件。→ 构造函数中务必显式设置。 - 多线程竞争:在不同线程同时调用
setCurrentState可能导致状态混乱。→ 使用LifecycleRegistry提供的同步方法或外部加锁。 - 资源泄漏:Owner被销毁后未将状态置为
DESTROYED,观察者仍然持有引用。→ 在destroy()方法中调用lifecycleRegistry.setCurrentState(State.DESTROYED)。 - 事件与状态混用:直接设置状态跳过了事件触发,可能导致观察者收不到对应回调。→ 优先使用
handleLifecycleEvent()。
⚠️ 警告:禁止在
getLifecycle()中返回new LifecycleRegistry(this),这会导致每次调用创建新对象,状态丢失且产生内存泄漏。必须使用同一个单例实例。3.6 性能优化
- 减少事件发送:若多个状态连续变化,可合并成一次
setCurrentState调用,降低观察者触发次数。 - 使用DefaultLifecycleObserver:Java 8+环境下,
DefaultLifecycleObserver比LifecycleObserver更高效,避免反射。 - 按需注册:只在需要时添加观察者,完成后及时移除
lifecycleRegistry.removeObserver(observer)。 - 避免在回调中做耗时操作:生命周期回调运行在UI线程,阻塞会导致ANR。
3.7 结构示意图
3.8 完整模板代码
以下是一个可直接复用的自定义LifecycleOwner模板,包含线程安全处理和资源清理:
public class SafeLifecycleOwner implements LifecycleOwner {
private final LifecycleRegistry lifecycleRegistry;
public SafeLifecycleOwner() {
lifecycleRegistry = new LifecycleRegistry(this);
lifecycleRegistry.setCurrentState(State.INITIALIZED);
}
@NonNull
@Override
public Lifecycle getLifecycle() {
return lifecycleRegistry;
}
public void onStart() {
lifecycleRegistry.handleLifecycleEvent(Event.ON_START);
}
public void onResume() {
lifecycleRegistry.handleLifecycleEvent(Event.ON_RESUME);
}
public void onPause() {
lifecycleRegistry.handleLifecycleEvent(Event.ON_PAUSE);
}
public void onStop() {
lifecycleRegistry.handleLifecycleEvent(Event.ON_STOP);
}
public void onDestroy() {
lifecycleRegistry.handleLifecycleEvent(Event.ON_DESTROY);
}
}
💡 最佳实践:在自定义Owner中实现
Closeable或AutoCloseable接口,在资源释放方法中自动设置DESTROYED状态,配合try-with-resources使用更加安全。