美文网首页
handler机制

handler机制

作者: 昵称被抢了 | 来源:发表于2020-01-06 14:02 被阅读0次

Handler包含两种一种是系统的Handler一种是开发者定义的handler,系统handler在ActivityThread类的初始化中使用饿加载进行初始化,主要处理一些系统的消息如回调四大组件生命周期、启动四大组件等。开发者自定义的handler通过自定义的handleMessage方法处理。

Handler机制也可叫异步消息机制,它主要由4个部分组成:Message,Handler,MessageQueue,Looper.简单的说,Handler获取当前线程中的looper对象,looper用来从存放Message的MessageQueue中取出Message,再有Handler进行Message的分发和处理.

Handler:可以发布或者处理一个消息或者操作一个Runnable,通过Handler发布消息,消息将只会发送到与它关联的消息队列,然也只能处理该消息队列中的消息

MessageQueue(消息队列):用来存放通过Handler发布的消息,通常附属于某一个创建它的线程,可以通过Looper.myQueue()得到当前线程的消息队列.

Message:消息的类型,在Handler类中的handleMessage方法中得到单个的消息进行处理.

源码角度分析Handler

应用程序的启动-->ActivityThread

一个应用程序启动时会通过孵化器(zygote)进程启动ActivityThread并调用main方法,main方法中初始化了ActivityThread类,ActivityThread中存在成员变量系统Handler->H采用饿加载的方式初始化了,系统Handler不做分析。

    public static void main(String[] args) {
       ......
       //初始化Looper循环器
        Looper.prepareMainLooper();
        //初始化ActivityThread并绑定
        ActivityThread thread = new ActivityThread();
        thread.attach(false, startSeq);
        ...
        //开启消息循环器
       Looper.loop();

        throw new RuntimeException("Main thread loop unexpectedly exited");
    }

消息循环器-->Looper

ActivityThread调用Looper的prepareMainLooper方法初始化消息队列MessageQueue并绑定当前线程.

  public static void prepareMainLooper() {
        prepare(false);
        synchronized (Looper.class) {
            if (sMainLooper != null) {
                throw new IllegalStateException("The main Looper has already been prepared.");
            }
            sMainLooper = myLooper();
        }
    }
    
        private static void prepare(boolean quitAllowed) {
        //获取当前线程对于的Looper
        if (sThreadLocal.get() != null) {
            throw new RuntimeException("Only one Looper may be created per thread");
        }
        //绑定当前线程
        sThreadLocal.set(new Looper(quitAllowed));
    }
    
   private Looper(boolean quitAllowed) {
          //初始化消息队列
        mQueue = new MessageQueue(quitAllowed);
        //当前线程
        mThread = Thread.currentThread();
    }

Looper.loop()启动消息循环


   public static void loop() {
       final Looper me = myLooper();
       if (me == null) {
           throw new RuntimeException("No Looper; Looper.prepare() wasn't called on this thread.");
       }
       //获取当前消息队列
       final MessageQueue queue = me.mQueue;
       Binder.clearCallingIdentity();
       final long ident = Binder.clearCallingIdentity();
       final int thresholdOverride =
               SystemProperties.getInt("log.looper."
                       + Process.myUid() + "."
                       + Thread.currentThread().getName()
                       + ".slow", 0);

       boolean slowDeliveryDetected = false;
        // 死循环开启消息循环器
       for (;;) {
         //获取消息队列中的消息
           Message msg = queue.next(); //next方法内也是个死循环,可能会锁住
           if (msg == null) {
               // 没有消息
               return;
           }
           ....

           try {
             //处理消息 msg.target是handler的引用,调用handler的dispatchMessage方法分发消息
               msg.target.dispatchMessage(msg);
               dispatchEnd = needEndTime ? SystemClock.uptimeMillis() : 0;
           } finally {
               if (traceTag != 0) {
                   Trace.traceEnd(traceTag);
               }
           }
             ....
           //回收Message
           msg.recycleUnchecked();
       }
   }

后面我们从hanlder开始分析。

Handler

Handler初始化时会获取到当前消息循环器和当前线程消息队列。


    public Handler() {
        this(null, false);
    }
     public Handler(Callback callback, boolean async) {
        mLooper = Looper.myLooper();
        mQueue = mLooper.mQueue;
        mCallback = callback;
        mAsynchronous = async;
    }

当handler调用sendMessage或者post方法时最终调用了sendMessageAtTime方法往消息队列添加了一个Message;

  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);
    }

消息队列-->MessageQueue

当Handler调用sendMessage或者post方法后最终会调用MessageQueue的enqueueMessage方法添加消息到消息队列。

boolean enqueueMessage(Message msg, long when) {
        synchronized (this) {
            msg.markInUse();
            msg.when = when;
            Message p = mMessages;
            boolean needWake;
            if (p == null || when == 0 || when < p.when) {
                msg.next = p;
                mMessages = msg;
                needWake = mBlocked;
            } else {
                needWake = mBlocked && p.target == null && msg.isAsynchronous();
                Message prev;
                for (;;) {
                    prev = p;
                    p = p.next;
                    if (p == null || when < p.when) {
                        break;
                    }
                    if (needWake && p.isAsynchronous()) {
                        needWake = false;
                    }
                }
                msg.next = p;
                prev.next = msg;
            }
            if (needWake) {
                nativeWake(mPtr);
            }
        }
        return true;
    }

Looper.loop方法在循环器中不停的调用messagequeue的next方法获取消息队列的message.

 Message next() {
        final long ptr = mPtr;
        if (ptr == 0) {
            return null;
        }
        int pendingIdleHandlerCount = -1; // -1 only during first iteration
        int nextPollTimeoutMillis = 0;
        for (;;) {
            if (nextPollTimeoutMillis != 0) {
                Binder.flushPendingCommands();
            }
            nativePollOnce(ptr, nextPollTimeoutMillis);
            synchronized (this) {
                final long now = SystemClock.uptimeMillis();
                Message prevMsg = null;
                //mMessges变量会在使用handler.sendMessage时赋值
                Message msg = mMessages;
                if (msg != null && msg.target == null) {
                    do {
                        prevMsg = msg;
                        msg = msg.next;
                    } while (msg != null && !msg.isAsynchronous());
                }
                if (msg != null) {
                    if (now < msg.when) {
                        nextPollTimeoutMillis = (int) Math.min(msg.when - now, Integer.MAX_VALUE);
                    } else {
                        mBlocked = false;
                        if (prevMsg != null) {
                            prevMsg.next = msg.next;
                        } else {
                            mMessages = msg.next;
                        }
                        msg.next = null;
                        msg.markInUse();
                        return msg;
                    }
                } else {
                    nextPollTimeoutMillis = -1;
                }
                if (mQuitting) {
                    dispose();
                    return null;
                }
                if (pendingIdleHandlerCount < 0
                        && (mMessages == null || now < mMessages.when)) {
                    pendingIdleHandlerCount = mIdleHandlers.size();
                }
                if (pendingIdleHandlerCount <= 0) {
                    mBlocked = true;
                    continue;
                }

                if (mPendingIdleHandlers == null) {
                    mPendingIdleHandlers = new IdleHandler[Math.max(pendingIdleHandlerCount, 4)];
                }
                mPendingIdleHandlers = mIdleHandlers.toArray(mPendingIdleHandlers);
            }

            for (int i = 0; i < pendingIdleHandlerCount; i++) {
                final IdleHandler idler = mPendingIdleHandlers[i];
                mPendingIdleHandlers[i] = null; 
                boolean keep = false;
                try {
                    keep = idler.queueIdle();
                } catch (Throwable t) {
                }
                if (!keep) {
                    synchronized (this) {
                        mIdleHandlers.remove(idler);
                    }
                }
            }

            pendingIdleHandlerCount = 0;

            nextPollTimeoutMillis = 0;
        }
    }

当next()返回了Message不为null时最终在Looper.loop()中调用handler的dispatchMessage方法进行当前Message的分发。

  msg.target.dispatchMessage(msg);

Handler

 public void dispatchMessage(Message msg) {
        if (msg.callback != null) {
            handleCallback(msg);
        } else {
            if (mCallback != null) {
                if (mCallback.handleMessage(msg)) {
                    return;
                }
            }
            handleMessage(msg);
        }
    }

如果设置了Message的callback时会直接执行Message的callback的run方法,如handler.post(new Runnable(){})时,就会给message的callback设置。
如果没有设置message的callback而是调用了handler的有参初始化方法初始化并给mCallback设置了一个不为null的值会调用初始化设置的方法,如:

Handler handler = new Handler(Looper.myLooper(), new Handler.Callback() {
            @Override
            public boolean handleMessage(@NonNull Message msg) {
                return false;
            }
        })

如果不给Message的callback初始化也不给Hanlder的mCalllback初始化,会调用handleMessage方法进行处理message。

相关文章

  • 深入理解Handler机制之引路篇

    要想深入理解Handler机制,就要理解: Android为何要引入Handler机制? Handler机制究竟是...

  • Handler机制小结

    Handler笔记 什么是handler机制?handler机制的主要成员1、handler:负责发送处理消息2、...

  • Android:Handler 机制和原理?

    一、Handler机制概述 Handler机制也可以说是消息机制,Handler的运行时需要MessageQueu...

  • Android消息机制

    Handler Android消息机制主要指的是Handler运行机制,Handler底层需要MessageQue...

  • Android 的消息机制

    Android 消息机制主要是指 Handler 的运行机制。 **Handler **Handler 的运行需要...

  • Android Handler机制详解

    Android Handler机制1--ThreadLocalAndroid Handler机制2--Looper...

  • 消息机制

    消息机制Handler的工作原理 Android中的消息机制主要就是指Handler的运行机制,而Handler的...

  • Handler机制整理

    Handler机制整理目录介绍1.关于handler消息机制图2.关于handler基本介绍3.使用handler...

  • android handler 机制 很简单

    1.android handler机制 handler机制,也就是android的异步消息处理机制。但是这个机制不...

  • Android的消息机制

    Handler Android消息机制主要是Handler的运行机制,Handler的运行需要底层的Message...

网友评论

      本文标题:handler机制

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