美文网首页
Handler源码学习(四) - Handler源码学习

Handler源码学习(四) - Handler源码学习

作者: Hoker_ | 来源:发表于2018-11-28 23:34 被阅读0次
    东拉西扯讲了那么多,终于到Handler了。

    一句话概括,Handler就是把特定任务发送到指定线程中执行,比如说UI刷新。如果没有这种需求,仅仅是需要线程的话,个人还是建议用线程池,因为代码更好写,而且线程池功能强大。

    Handler的构造方法在前面文章里已经看过了,这里就不再继续说明。主要还是看看发送任务的方法,sendMessageAtTime(),其他的发送消息的方法最终都会调用到这个:

        public boolean sendMessageAtTime(Message msg, long uptimeMillis) {
            MessageQueue queue = mQueue;
            if (queue == null) {
                RuntimeException e = new RuntimeException(
                        this + " sendMessageAtTime() called with no mQueue");
                Log.w("Looper", e.getMessage(), e);
                return false;
            }
            return enqueueMessage(queue, msg, uptimeMillis);
        }
    
        private boolean enqueueMessage(MessageQueue queue, Message msg, long uptimeMillis) {
            msg.target = this;
            if (mAsynchronous) {
                msg.setAsynchronous(true);
            }
            return queue.enqueueMessage(msg, uptimeMillis);
        }
    

    方法非常简单,就是对Handler绑定的消息队列发送消息,需要注意的是:

    msg.target = this;
    

    这里会把Handler对象的引用也放到消息队列里,方便消息队列来识别是哪个Handler的消息被消费。

    结合前面的几个分析,Handler源码也没啥特别好讲的了,在说下平时使用Handler经常出的内存泄漏问题吧。

    要知道,android内存回收,是采用GCRoot判断引用是否可达来决策的,换句话说,以GCRoot为起点,它可以引用到的对象,在GC时都不会被回收,其他的则会被回收,那么GCRoot有哪些呢:

    • 运行中的线程
    • 静态对象
    • 来自native code中的引用

    一般的,我们大多数都是在Activity里这么写上handler:

        private final Handler handler = new Handler(){
            @Override
            public void handleMessage(Message msg) {
                super.handleMessage(msg);
                //执行任务
            }
        };
    

    但是,内部类(包括匿名类)来会隐式地持有一个外部类对象的引用(在这里就是Activity,不然是无法在里Handler来操作Activity中的View的)而且,我们使用Handler绑定的都是主线程,而主线程的生命周期显然是整个APP运行时期。假如使用Handler的postDelayed()方法,那么在设定的delay到达之前,会有一条Looper->MessageQueue -> Message -> Handler -> Activity的链,导致Activity被持有引用而无法被回收。

    解决方法也很简单,用静态类+弱引用:

        public static class MyHandler extends Handler{
    
            WeakReference<MainActivity> mWeakReference;
            
            public MyHandler(MainActivity activity){
                mWeakReference=new WeakReference<MainActivity>(activity);
            }
            
            @Override
            public void handleMessage(Message msg){
                final MainActivity activity=mWeakReference.get();
                if(activity!=null){
                    super.handleMessage(msg);
                    //执行任务
                }
            }
        }
    

    由于是弱应用,这样在Activity不再使用时,可以被GC掉。

    总结:Handler是就是安卓的消息机制,熟悉其原理对平时工作有很大的帮助。

    相关文章

      网友评论

          本文标题:Handler源码学习(四) - Handler源码学习

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