Handler机制的源码分析

Handler,MessageQueue,Looper的关系

  • Looper的做用是在线程中处理消息的异步

  • MessageQueue用来存储消息的队列ide

  • Handler使用来定义具体处理消息的方式,以及发送消息;Android主线程中持有一个能够更新UI的Handler;对其余的线程,若是须要处理消息,能够本身new一个Handler在线程的 run 方法中。oop

  • ThreadLocal:MessageQueue对象,和Looper对象在每一个线程中都只会有一个对象,怎么能保证它只有一个对象,就经过ThreadLocal来保存。Thread Local是一个线程内部的数据存储类,经过它能够在指定线程中存储数据,数据存储之后,只有在指定线程中能够获取到存储到数据,对于其余线程来讲则没法获取到数据。源码分析

一.Looperui

源码分析: Looper.prepare()方法;建立一个Looper的实例,可是该实例在一个线程中只能有一个;保存在ThreadLocal中,若是发现已经存在了Looper对象,会抛出一个异常。this

public static void prepare() {
        prepare(true);
    }
    private static void prepare(boolean quitAllowed) {
        if (sThreadLocal.get() != null) {
            throw new RuntimeException("Only one Looper may be created per thread");
        }
        sThreadLocal.set(new Looper(quitAllowed));
    }

Looper.loop()方法;loop()方法中有一个无限的循环。for(;;)那一段;线程执行到loop()方法以后会一直留在loop()方法中,直到被打断终止 (源码能够看出,发送空消息就能够打断该循环,终止该线程)spa

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;
        // Make sure the identity of this thread is that of the local process,
        // and keep track of what that identity token actually is.
        Binder.clearCallingIdentity();
        final long ident = Binder.clearCallingIdentity();

//死循环
        for (;;) {
            Message msg = queue.next(); // might block
            if (msg == null) {
                // No message indicates that the message queue is quitting.
                return;
            }
            // This must be in a local variable, in case a UI event sets the logger
            final Printer logging = me.mLogging;
            if (logging != null) {
                logging.println(">>>>> Dispatching to " + msg.target + " " +
                        msg.callback + ": " + msg.what);
            }
            final long traceTag = me.mTraceTag;
            if (traceTag != 0) {
                Trace.traceBegin(traceTag, msg.target.getTraceName(msg));
            }
            try {
                msg.target.dispatchMessage(msg);
            } finally {
                if (traceTag != 0) {
                    Trace.traceEnd(traceTag);
                }
            }
            if (logging != null) {
                logging.println("<<<<< Finished to " + msg.target + " " + msg.callback);
            }
            // Make sure that during the course of dispatching the
            // identity of the thread wasn't corrupted.
            final long newIdent = Binder.clearCallingIdentity();
            if (ident != newIdent) {
                Log.wtf(TAG, "Thread identity changed from 0x"
                        + Long.toHexString(ident) + " to 0x"
                        + Long.toHexString(newIdent) + " while dispatching to "
                        + msg.target.getClass().getName() + " "
                        + msg.callback + " what=" + msg.what);
            }
            msg.recycleUnchecked();
        }
    }

二.Handler线程

重要的构造方法:code

  • 传入某个线程thread的Looper对象;这样这个Handler就是该thread的Handler了(和在该thread的run方法中直接new一个没有参数的Handler的效果是同样的;可是在外部定义可使咱们更好使用)
/**
    *  Use the provided {@link Looper} instead of the default one.
    *
    *  @param looper The looper, must not be null.
    */
   public Handler(Looper looper) {
       this(looper, null, false);
   }

   /**
    * Default constructor associates this handler with the {@link Looper} for the
    * current thread.
    *
    * If this thread does not have a looper, this handler won't be able to receive messages
    * so an exception is thrown.
    */
   public Handler() {
       this(null, false);
   }

三.MessageQueue对象

MessagerQueue是一个单向链表

HandlerThread

HandlerThread是Android系统本身实现的一个能够实现 处理异步消息 的线程。简单来讲就是和UI线程是同样的原理,经过Looper和Message通讯,让该线程为咱们服务。

具体能够看源码就能知道他的原理(咱们本身也能够写这样的线程,可是系统给咱们的老是要好一点的)

@Override
    public void run() {
        mTid = Process.myTid();
        Looper.prepare();
        synchronized (this) {
            mLooper = Looper.myLooper();
            notifyAll();
        }
        Process.setThreadPriority(mPriority);
        onLooperPrepared();
        Looper.loop();
        mTid = -1;
    }

HandlerThread的使用

HandlerThread workThread = new HandlerThread();
workThread.start();
Handler handler = new Handler(workThread.getLooper());
相关文章
相关标签/搜索