通过LifecycleOwner,优雅的使用Handler
目前的问题
Handler的使用在Android日常开发中占用很大的比重,尤其在界面开发中,经常被用来做一些延迟执行的任务。但Handler带来的问题也很多,最常见的比如页面退出未执行的任务没有被移除导致内存泄漏,以及可能的由于界面已不存在而导致的崩溃。如下,如果不及时移除就可能造成上述问题。
mHander.postDelayed(new Runnable() {
@Override
public void run() {
//do something
}
},1000);
这些问题一般都比较容易想到,也容易解决,常用的方式是缓存一个Runnable变量在使用的类中,然后在页面生命周期结束移除
类变量:
Runnable mDelayedRunnable;
初始化:
mDelayedRunnable = new Runnable() {
@Override
public void run() {
//do something
}
};
mHander.postDelayed(mDelayedRunnable,1000);
...
生命周期结束(Activity,Fragment)
void onDestroy () {
mHander.removeCallbacks(mDelayedRunnable);
}
上面的这种做法可以解决Handler的不当使用带来的问题,但是有个比较恶心的问题,太不优雅,太多的行数,要非常小心remove的问题,浪费时间精力在这样的无技术含量的代码上让人苦恼。
解决方案
使用support 27包下,Android提供了LifecycleOwner的实现,提供一种可对Activity,Fragment的生命周期监听的一种实现方式,从基础api层面做了很好的支持,Android Architecture Components架构(包括LiveData,ViewModel等)也是主要基于此来完成的,不熟悉AAC的可以参考下之前的开源项目 KnowWeather。
实现方式是对原Runnable进行代理,然后对LifecycleOwner的生命周期进行监听,GenericLifecycleObserver是api里提供的一个接口,会在实现了LifecycleOwner的实现类的一些关键生命周期里回调,不限于onDestory,如果任务在然后在Lifecycle.Event.ON_DESTROY事件前被执行,移除监听,反之在GenericLifecycleObserver的Lifecycle.Event.ON_DESTROY事件调时移除未执行的任务。
public class LifecycleRunnableWrapper implements Runnable {
private Runnable mOriginRunnable;
private LifecycleOwner mLifecycleOwner;
private GenericLifecycleObserver mLifecycleObserver;
LifecycleRunnableWrapper(LifecycleOwner lifecycleOwner, final Handler handler,final Runnable originRunnable) {
if(originRunnable == null || lifecycleOwner == null) {
return;
}
this.mLifecycleOwner = lifecycleOwner;
this.mOriginRunnable = originRunnable;
mLifecycleObserver = new GenericLifecycleObserver() {
@Override
public void onStateChanged(LifecycleOwner source, Lifecycle.Event event) {
if(event == Lifecycle.Event.ON_DESTROY) {
if(mLifecycleOwner!=null ) {
mLifecycleOwner.getLifecycle().removeObserver(this);
}
handler.removeCallbacks(LifecycleRunnableWrapper.this);
}
}
};
mLifecycleOwner.getLifecycle().addObserver(mLifecycleObserver);
}
@Override
public void run() {
if(mOriginRunnable!=null && mLifecycleOwner!=null) {
mOriginRunnable.run();
mLifecycleOwner.getLifecycle().removeObserver(mLifecycleObserver);
}
}
}
如果每次使用Runnable都是要上面的封装方式看起来也很麻烦,在TaskScheduler已经对上述内容作了封装,可以很方便的使用
默认onDestory移除未执行的任务
TaskScheduler.runOnUIThread(this,new Runnable() {
@Override
public void run() {
Log.i("LifeFragment","runTask with life");
}
},5000);
可指定在特定生命周期移除未执行任务,如onStop
TaskScheduler.runOnUIThread(this, Lifecycle.Event.ON_STOP, new Runnable() {
@Override
public void run() {
Log.i("LifeFragment","runTask with life on Stop");
}
},5000);
可外部传入Handler
TaskScheduler.runLifecycleRunnable(this, TaskScheduler.ioHandler(), new Runnable() {
@Override
public void run() {
Log.i("LifeFragment","io thread runTask with life");
}
},5000);
更多使用方式,请查看TaskScheduler源码实现。
转载自:https://juejin.cn/post/6844903725497057294