Handler机制的源码分析
2017-10-18 19:14
281 查看
Handler,MessageQueue,Looper的关系
Looper的作用是在线程中处理消息的MessageQueue用来存储消息的队列
Handler使用来定义具体处理消息的方式,以及发送消息;Android主线程中持有一个可以更新UI的Handler;对其他的线程,如果需要处理消息,可以自己new一个Handler在线程的 run 方法中。
ThreadLocal:MessageQueue对象,和Looper对象在每个线程中都只会有一个对象,怎么能保证它只有一个对象,就通过ThreadLocal来保存。Thread Local是一个线程内部的数据存储类,通过它可以在指定线程中存储数据,数据存储以后,只有在指定线程中可以获取到存储到数据,对于其他线程来说则无法获取到数据。
一.Looper
源码分析:
Looper.prepare()方法;创建一个Looper的实例,但是该实例在一个线程中只能有一个;保存在ThreadLocal中,如果发现已经存在了Looper对象,会抛出一个异常。
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()方法中,直到被打断终止 (源码可以看出,发送空消息就可以打断该循环,终止该线程)
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
重要的构造方法:
传入某个线程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());
相关文章推荐
- Handler机制源码分析(异步一)
- Android源码分析之Handler机制
- 源码分析 — Handler机制(线程间通信)
- Android源码分析--Handler机制的实现与工作原理
- Android Handler机制(一)---Message源码分析
- android源码分析系列(一):Handler机制
- 从源码角度分析java层Handler机制
- Handler机制流程梳理、源码分析
- Android Handler机制源码分析
- Android源码分析笔记--Handler机制
- handler机制的源码分析
- handler机制(二)源码分析
- Handler机制-从源码角度分析
- 通过源码分析Android Handler机制
- 源码分析Handler机制
- Handler机制.源码分析
- handler机制 源码分析 梳理
- [置顶] Android源码分析——Looper,Messagequeue,Message,handler初始化及handler机制简介
- jvm hotspot 源码分析 RandomAccessfile vs FileChannel 写文件
- 轻量级前端MVVM框架avalon源码分析