目前的问题

Handler的使用在Android日常开发中占用很大的比重,尤其在界面开发中,经常被用来做一些延迟执行的任务。但Handler带来的问题也很多,最常见的比如页面退出未执行的任务没有被移除导致内存泄漏,以及可能的由于界面已不存在而导致的崩溃。如下,如果不及时移除就可能造成上述问题。

1
2
3
4
5
6
mHander.postDelayed(new Runnable() {
@Override
public void run() {
//do something
}
},1000);

这些问题一般都比较容易想到,也容易解决,常用的方式是缓存一个Runnable变量在使用的类中,然后在页面生命周期结束移除

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
类变量:
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事件调时移除未执行的任务。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
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移除未执行的任务

1
2
3
4
5
6
TaskScheduler.runOnUIThread(this,new Runnable() {
@Override
public void run() {
Log.i("LifeFragment","runTask with life");
}
},5000);

可指定在特定生命周期移除未执行任务,如onStop

1
2
3
4
5
6
TaskScheduler.runOnUIThread(this, Lifecycle.Event.ON_STOP, new Runnable() {
@Override
public void run() {
Log.i("LifeFragment","runTask with life on Stop");
}
},5000);

可外部传入Handler

1
2
3
4
5
6
TaskScheduler.runLifecycleRunnable(this, TaskScheduler.ioHandler(), new Runnable() {
@Override
public void run() {
Log.i("LifeFragment","io thread runTask with life");
}
},5000);

更多使用方式,请查看TaskScheduler源码实现。