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