目前的问题
Handler的使用在Android日常开发中占用很大的比重,尤其在界面开发中,经常被用来做一些延迟执行的任务。但Handler带来的问题也很多,最常见的比如页面退出未执行的任务没有被移除导致内存泄漏,以及可能的由于界面已不存在而导致的崩溃。如下,如果不及时移除就可能造成上述问题。
1 2 3 4 5 6
| mHander.postDelayed(new Runnable() { @Override public void run() { } },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() { } }; 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源码实现。