48、Lifecycle组件:LifecycleOwner、LifecycleObserver、自定义生命周期感知组件
说实话,Android开发里最让人头疼的问题之一,就是生命周期管理。我记得刚入行那会儿,经常在Activity的onDestroy里忘记解注册,结果内存泄漏找上门来。后来Google推出了Lifecycle组件,这玩意儿说白了就是帮我们自动感知生命周期,再也不用手动去写那些又臭又长的回调了。
今天我们就来聊聊Lifecycle组件的核心三件套:LifecycleOwner、LifecycleObserver,以及如何自定义生命周期感知组件。我会结合我自己的踩坑经历,把这块内容讲透。
一、LifecycleOwner:谁拥有生命周期?
LifecycleOwner是一个接口,只有一个方法——getLifecycle()。谁实现了这个接口,谁就拥有了生命周期管理能力。AppCompatActivity和Fragment默认就实现了它,所以我们直接用就行。
但这里有个坑:自定义View如果也想成为LifecycleOwner,需要自己实现。我曾经在一个自定义相机预览View里踩过这个坑,因为没正确处理生命周期,导致相机资源释放不及时,引发了一系列诡异问题。
核心要点:LifecycleOwner负责分发生命周期事件,它内部维护了一个LifecycleRegistry对象。
来看一个自定义LifecycleOwner的例子:
public class MyLifecycleOwner implements LifecycleOwner {
private LifecycleRegistry lifecycleRegistry;
public MyLifecycleOwner() {
lifecycleRegistry = new LifecycleRegistry(this);
}
@Override
public Lifecycle getLifecycle() {
return lifecycleRegistry;
}
// 手动触发生命周期事件
public void onCreate() {
lifecycleRegistry.handleLifecycleEvent(Lifecycle.Event.ON_CREATE);
}
public void onStart() {
lifecycleRegistry.handleLifecycleEvent(Lifecycle.Event.ON_START);
}
public void onResume() {
lifecycleRegistry.handleLifecycleEvent(Lifecycle.Event.ON_RESUME);
}
public void onPause() {
lifecycleRegistry.handleLifecycleEvent(Lifecycle.Event.ON_PAUSE);
}
public void onStop() {
lifecycleRegistry.handleLifecycleEvent(Lifecycle.Event.ON_STOP);
}
public void onDestroy() {
lifecycleRegistry.handleLifecycleEvent(Lifecycle.Event.ON_DESTROY);
}
}
嗯,这里要注意:LifecycleRegistry是线程安全的,但事件分发顺序必须正确。你不能在ON_CREATE之前就发ON_START,否则会抛异常。
二、LifecycleObserver:如何监听生命周期?
LifecycleObserver是一个标记接口,本身没有方法。真正起作用的是配合注解或者DefaultLifecycleObserver使用。
我个人习惯用DefaultLifecycleObserver,因为它是Java 8+的推荐方式,不用反射,性能更好。
public class MyObserver implements DefaultLifecycleObserver {
private static final String TAG = "MyObserver";
@Override
public void onCreate(LifecycleOwner owner) {
Log.d(TAG, "onCreate: 组件创建了");
}
@Override
public void onStart(LifecycleOwner owner) {
Log.d(TAG, "onStart: 组件可见了");
}
@Override
public void onResume(LifecycleOwner owner) {
Log.d(TAG, "onResume: 组件可交互了");
}
@Override
public void onPause(LifecycleOwner owner) {
Log.d(TAG, "onPause: 组件暂停了");
}
@Override
public void onStop(LifecycleOwner owner) {
Log.d(TAG, "onStop: 组件不可见了");
}
@Override
public void onDestroy(LifecycleOwner owner) {
Log.d(TAG, "onDestroy: 组件销毁了");
}
}
你想想看,有了这个Observer,我们只需要在Activity里这样注册:
public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
getLifecycle().addObserver(new MyObserver());
}
}
是不是很清爽?再也不用手动在onResume里开启定位、在onPause里关闭定位了。Observer自己就能感知到。
小技巧:如果你用的是Java 7或者需要兼容旧版本,可以用注解方式:@OnLifecycleEvent(Lifecycle.Event.ON_RESUME)。但注意,这种方式基于反射,性能略差。
三、自定义生命周期感知组件
这才是今天的重头戏。什么叫生命周期感知组件?说白了,就是组件自己能感知到宿主的生命周期,自动做该做的事。
我曾经写过一个位置监听组件,需要在Activity可见时开始定位,不可见时停止定位。用传统方式,我得在Activity里写一堆模板代码。用Lifecycle组件后,代码变成了这样:
public class LocationManager implements DefaultLifecycleObserver {
private Context context;
private LocationListener listener;
public LocationManager(Context context, LocationListener listener) {
this.context = context;
this.listener = listener;
}
@Override
public void onResume(LifecycleOwner owner) {
startLocationUpdates();
}
@Override
public void onPause(LifecycleOwner owner) {
stopLocationUpdates();
}
private void startLocationUpdates() {
// 实际的位置请求代码
Log.d("LocationManager", "开始定位...");
}
private void stopLocationUpdates() {
// 停止定位
Log.d("LocationManager", "停止定位...");
}
public interface LocationListener {
void onLocationChanged(double latitude, double longitude);
}
}
然后在Activity里:
public class MapActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_map);
LocationManager locationManager = new LocationManager(this,
(lat, lng) -> {
// 更新地图位置
});
getLifecycle().addObserver(locationManager);
}
}
看到了吗?Activity里一行生命周期代码都没写,但定位组件却能在正确的时机开启和关闭。这就是生命周期感知的魅力。
避坑指南:我曾经在自定义组件里直接持有Activity的引用,结果导致内存泄漏。正确的做法是:组件只依赖LifecycleOwner接口,不要依赖具体的Activity或Fragment。这样既解耦,又安全。
四、生命周期状态与事件的关系
为了让你更清楚地理解Lifecycle的工作机制,我画了一张图:
这张图展示了Lifecycle的五个状态和六个事件。状态是当前所处的生命周期阶段,事件则是触发状态转换的动作。举个例子:当Activity执行onCreate时,Lifecycle会发出ON_CREATE事件,状态从INITIALIZED变为CREATED。
这里有个关键点:状态是当前所处的阶段,事件是正在发生的动作。Observer监听的是事件,而Owner管理的是状态。
五、实战:封装一个生命周期感知的倒计时组件
最后,我分享一个我自己项目里用过的倒计时组件。它能在Activity可见时倒计时,不可见时暂停,再次可见时继续。完全不用在Activity里写任何生命周期代码。
public class LifecycleCountDown implements DefaultLifecycleObserver {
private CountDownTimer timer;
private long totalMillis;
private long remainingMillis;
private OnTickListener listener;
private boolean isPaused = false;
public LifecycleCountDown(long totalMillis, OnTickListener listener) {
this.totalMillis = totalMillis;
this.remainingMillis = totalMillis;
this.listener = listener;
}
@Override
public void onResume(LifecycleOwner owner) {
if (isPaused && remainingMillis > 0) {
startTimer();
}
}
@Override
public void onPause(LifecycleOwner owner) {
if (timer != null) {
timer.cancel();
isPaused = true;
}
}
@Override
public void onDestroy(LifecycleOwner owner) {
if (timer != null) {
timer.cancel();
}
}
public void start() {
startTimer();
}
private void startTimer() {
timer = new CountDownTimer(remainingMillis, 1000) {
@Override
public void onTick(long millisUntilFinished) {
remainingMillis = millisUntilFinished;
if (listener != null) {
listener.onTick(millisUntilFinished);
}
}
@Override
public void onFinish() {
remainingMillis = 0;
if (listener != null) {
listener.onFinish();
}
}
}.start();
isPaused = false;
}
public interface OnTickListener {
void onTick(long millisUntilFinished);
void onFinish();
}
}
使用方式:
LifecycleCountDown countDown = new LifecycleCountDown(60000,
new LifecycleCountDown.OnTickListener() {
@Override
public void onTick(long millisUntilFinished) {
textView.setText("剩余:" + millisUntilFinished / 1000 + "秒");
}
@Override
public void onFinish() {
textView.setText("倒计时结束");
}
});
getLifecycle().addObserver(countDown);
countDown.start();
这个组件我用了好几年,从来没出过内存泄漏的问题。核心思想就一句话:让组件自己管理自己的生命周期行为,宿主只负责注册。
总结一下:Lifecycle组件把我们从繁琐的生命周期管理中解放了出来。LifecycleOwner提供生命周期源,LifecycleObserver监听生命周期事件,两者结合就能做出各种优雅的自定义组件。记住,好的架构设计,就是让代码自己管好自己。
公众号:蓝海资料掘金营,微信deep3321