美文网首页
Android Handler机制

Android Handler机制

作者: 京写 | 来源:发表于2020-08-07 10:14 被阅读0次
    handler机制图解
    1. handler线程安全的
    2. handler怎么用
    • post(Runnable)
    • postDelayed(Runnable,long);
    • sendMessage
    • sendMessageDelayed
      参考文章

    Android UI线程ActivityThread.main会默认创建一个looper,默认调用looper.prepare和looper.loop方法
    如果想在子线程中建立Handler来处理业务,需要手动先调用Looper.prepare方法,之后创建Handler,最后在调用Looper.loop方法。

    实例代码

    // 创建一个子线程,并在子线程中创建一个Handler,且重写handleMessage
            new Thread(new Runnable() {
                @Override
                public void run() {
                    Looper.prepare();
                    subHandler = new Handler() {
                        @Override
                        public void handleMessage(Message msg) {
                            super.handleMessage(msg);
                            // 处理消息
                            switch (msg.what) {
                                case MSG_MAIN_TO_SUB:
                                    Log.e(TAG, "接收到消息: " +  Thread.currentThread().getName() + ","+ msg.obj);
                                    break;
                                default:
                                    break;
                            }
                        }
                    };
                    Looper.loop();
                }
            }).start();
    

    这样可以实现从主线程向子线程发送消息。
    Looper:一个线程最多只存在一个Looper对象,如果没有,去创建一个Looper,并存放在sThreadLocal中。

      public static void prepare() {
            prepare(true);
        }
    
        private static void prepare(boolean quitAllowed) {
            // 规定了一个线程只有一个Looper,也就是一个线程只能调用一次Looper.prepare()
            if (sThreadLocal.get() != null) {
                throw new RuntimeException("Only one Looper may be created per thread");
            }
            // 如果当前线程没有Looper,那么就创建一个,存到sThreadLocal中
            sThreadLocal.set(new Looper(quitAllowed));
        }
    

    Looper会创建一个MessageQueue对象

     private Looper(boolean quitAllowed) {
            // 创建了MessageQueue,并供Looper持有
            mQueue = new MessageQueue(quitAllowed);
            // 让Looper持有当前线程对象
            mThread = Thread.currentThread();
        }
    

    MessageQueue存放Message

    Looper.loop

      public static void loop() {
            // 得到当前线程的Looper对象
            final Looper me = myLooper();
            if (me == null) {
                throw new RuntimeException("No Looper; Looper.prepare() wasn't called on this thread.");
            }
            // 得到当前线程的MessageQueue对象
            final MessageQueue queue = me.mQueue;
            
            // 无关代码
            ......
            
            // 死循环
            for (;;) {
                // 不断从当前线程的MessageQueue中取出Message,当MessageQueue没有元素时,方法阻塞
                Message msg = queue.next(); // might block
                if (msg == null) {
                    // No message indicates that the message queue is quitting.
                    return;
                }
                // Message.target是Handler,其实就是发送消息的Handler,这里就是调用它的dispatchMessage方法
                msg.target.dispatchMessage(msg);
                // 回收Message
                msg.recycleUnchecked();
            }
        }
    

    Message信息携带者,一个线程可以有多个
    Handler发送消息以及消息的回调实现,一个线程可以有多个Handler
    Looper消息遍历者,从MessageQueue中循环取出Message进消息行处理,一个线程只有一个
    MessageQueue消息队列,存放Handler发送消息,供Looper循环取消息,一个线程只有一个
    sendMessageDelayed方法最终都是会被调到,只是延迟时间可能为0,

    Handler相关面试问题

    • Looper.loop可以停止吗
      答:quit和quitSafely方法停止looper
    • Android中,有哪些是基于Handler来实现通信的?
      答:App的运行、更新UI、AsyncTask、Glide、RxJava等
    • 处理Handler消息,是在哪个线程?一定是创建Handler的线程么?
      答:创建Handler所使用的Looper所在的线程
    • 消息是如何插入到MessageQueue中的?
      答: 是根据when在MessageQueue中升序排序的,when=开机到现在的毫秒数+延时毫秒数
    • 当MessageQueue没有消息时,它的next方法是阻塞的,会导致App ANR么?
      答:不会导致App的ANR,是Linux的pipe机制保证的,阻塞时,线程挂起;需要时,唤醒线程
    • 子线程中可以使用Toast么?
      答:可以使用,但是Toast的显示是基于Handler实现的,所以需要先创建Looper,然后调用Looper.loop。
    • Looper.loop()是死循环,可以停止么?
      答:可以停止,Looper提供了quit和quitSafely方法
    • Handler内存泄露怎么解决?
      答: 静态内部类+弱引用 、Handler的removeCallbacksAndMessages等方法移除MessageQueue中的消息

    相关文章

      网友评论

          本文标题:Android Handler机制

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