likes
comments
collection
share

通过LifecycleOwner,优雅的使用Handler

作者站长头像
站长
· 阅读数 46

目前的问题

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
评论
请登录