美文网首页
WeakHandler继续优化

WeakHandler继续优化

作者: 耗子JF | 来源:发表于2019-08-06 23:07 被阅读0次

    将Handler改成WeakHandler弱引用持有Context以后,新的问题来了,做了延迟操作以后关闭Activity,作为严谨的(强迫症)程序猿,我们还是应该手动去清除handler可能执行的延迟任务Message。有没有办法每次页面生命周期OnPause或者OnDestory的时候自动帮我们完成这个清理呢?这个时候Lifecycle这样的好东西就能帮我们实现这个愿望了!

    //重点1:首先记得把WeakHandler继承LifecycleObserver ,这样我们就能观察引用的生命周期了
    public class WeakHandler<T extends WeakHandler.WeakHandlerCallBack> extends Handler implements LifecycleObserver {
    
      //新增一个记录我们发送消息的容器用于回收可能存在的延迟任务
      private Set<Integer> msgList = new HashSet<>();
    
      public WeakHandler(T t) {
            this.weakReference = new WeakReference<>(t);
            //重点2:在这里设置生命周期观察
            if(weakReference.get() != null && weakReference.get() instanceof LifecycleOwner){
                ((LifecycleOwner) weakReference.get()).getLifecycle().addObserver(this);
            }
        }
      
        /**重点3:通过源码我们发现,所有sendMessage,以及Post任务最终都是通过这个函数发出去的,
          *我们重写这个函数即可记录所有参与发送的延迟任务(为了安全起见,
          *我们把所有发送过得任务都记录下来)
        */
        @Override
        public boolean sendMessageAtTime(Message msg, long uptimeMillis) {
            /**实际开发中,如果你的项目页面发射的数据比较多(个人感觉不会太多,所有记录了全部数据),
              *可以加上uptimeMillis>0这个过滤条件,另外Post掉的Runner消息也可以采用一样
              *的手段在这里记录,然后再后续移除里进行Remove操作,我就不写了*/
            if(msg != null){
                msgList.add(msg.what);
            }
            return super.sendMessageAtTime(msg, uptimeMillis);
        }
    
       /**重点4:注册生命周期ON_STOP观察者
          *这样在我们的引用页面调用OnStop的时候我们就能收到信息做remove处理了,很简单吧!
          *同理,有些页面我们不想在OnStop处理,而是需要在OnDestory处理,
          *那我们只需要注册ON_DESTORY然后进行对应的处理就可以了
        */
        @OnLifecycleEvent(Lifecycle.Event.ON_STOP)
        public void onStop(@NotNull LifecycleOwner owner){
            LogW.i("WeakHandler LifecycleOwner["+owner+"] onStop");
            cleanMsgQuee();
        }
    
        //这里也能处理Post任务,自行参考这个就可以搞定了
        public synchronized void cleanMsgQuee(){
            if(msgList != null && msgList.size() > 0){
                Iterator<Integer> iterator = msgList.iterator();
                while (iterator.hasNext()) {
                    Integer what = iterator.next();
                    if(what != null){
                        removeMessages(what);
                        iterator.remove();
                    }
                    LogW.i("--->>> cleanMsgQuee remove:"+what);
                }
            }
        }
    }
    

    整个实现是不是贼简单,hmm,这下可以直接无脑初始化以后调用了,再也不用担心忘记回收Message的问题了!其实这里面还有可以优化的地方,比如重复发送信息如何记录,以及已经完成的任务应该及时去掉,我这里主要提供一个思路,要是有兴趣的可以深入优化一下!

    Back:简单好用的解决Handler持有引用导致内存泄漏的方法

    相关文章

      网友评论

          本文标题:WeakHandler继续优化

          本文链接:https://www.haomeiwen.com/subject/nrvgdctx.html