最近对android Handler实现原理比较感兴趣,抽空分析了一下Handler java层实现原理,梳理如下
main loop 在哪里创建的?SystemServer run ActivityThread main
enqueueMessage逻辑?
类图:
1.loop.prepare 会检查当前线程是否存在loop 有则抛异常 否则创建loop实例 因此一个线程只能存在一个loop实例 该实例会创建一个messagequeue 故一个线程只有一个 messagequeue
2.loop.loop会让该实例所在线程进入死循环 不断从从messageQueue中获取消息调用msg.target.disparchMessage
3.创建handler时会获取所在线程的loop 并与loop的messageQueue关联
4.sendMssage 方法会将target设置handler自身并将message加入到messageQueue,同样post(Runnable)方法也一样
5.loop在接收到Message后获取其target然后调用dispatchMessage 派发消息调用handMessage
以下代码红色部分解释以上1、2、3、4、5步
- Looper prepare()
private static void prepare(boolean quitAllowed) {
//检查所在线程是否存在loop 如存在抛出异常,所以prepare在同一个线程里只可以调用一次,即同一个线程只可有一个loop if (sThreadLocal.get() != null) { throw new RuntimeException("Only one Looper may be created per thread"); }
//否则创建loop sThreadLocal.set(new Looper(quitAllowed)); }
private Looper(boolean quitAllowed) {
//looper创建消息队列 mQueue = new MessageQueue(quitAllowed); mThread = Thread.currentThread(); }
- Looper.java loop()
/** * Run the message queue in this thread. Be sure to call * {@link #quit()} to end the 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 Printer logging = me.mLogging; if (logging != null) { logging.println(">>>>> Dispatching to " + msg.target + " " + msg.callback + ": " + msg.what); } //派发消息 msg.target.dispatchMessage(msg); 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 myLooper()
public Handler(Callback callback, boolean async) {
if (FIND_POTENTIAL_LEAKS) {
final Class<? extends Handler> klass = getClass();
if ((klass.isAnonymousClass() || klass.isMemberClass() || klass.isLocalClass()) &&
(klass.getModifiers() & Modifier.STATIC) == 0) {
Log.w(TAG, "The following Handler class should be static or leaks might occur: " +
klass.getCanonicalName());
}
}
//获取looper实例
mLooper = Looper.myLooper();
if (mLooper == null) {
throw new RuntimeException(
"Can't create handler inside thread that has not called Looper.prepare()");
}
//获取looper消息队列 mQueue = mLooper.mQueue; mCallback = callback; mAsynchronous = async; }
4.Handler sendMessage
/** * Return the Looper object associated with the current thread. Returns * null if the calling thread is not associated with a Looper. */ public static @Nullable Looper myLooper() { return sThreadLocal.get(); }
public final boolean sendMessage(Message msg)
{
return sendMessageDelayed(msg, 0);
}
public final boolean sendMessageDelayed(Message msg, long delayMillis)
{
if (delayMillis < 0) {
delayMillis = 0;
}
return sendMessageAtTime(msg, SystemClock.uptimeMillis() + delayMillis);
}
美丽的///分隔线///
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) {
//将target设置为自己 即loop dispatchMessage方法中被调用
//msg.target.dispatchMessage(msg);
msg.target = this;
if (mAsynchronous) {
msg.setAsynchronous(true);
}
return queue.enqueueMessage(msg, uptimeMillis);
}
//post 方法是生成了一个带Callback的Message
//调用msg的target target是发送Message的Handler
msg.target.dispatchMessage(msg);
/**
* Handle system messages here.
*/
public void dispatchMessage(Message msg) {
//优先处理回调再处理handleMessage
if (msg.callback != null) {
handleCallback(msg);
} else {
if (mCallback != null) {
if (mCallback.handleMessage(msg)) {
return;
}
}
handleMessage(msg);
}
}
private static Message getPostMessage(Runnable r) {
Message m = Message.obtain();
m.callback = r;
return m;
}
5.Looper loop()
消息的回收利用机制,是维护了一个池,这个池以链表方式存储 当获取消息时从链头取出,若消息池中没有可复用则创建新消息,当回收(把消息池中添加)消息时将新回收消息添加至链头
回收消息代码片段:
/**
* Recycles a Message that may be in-use.
* Used internally by the MessageQueue and Looper when disposing of queued Messages.
*/
void recycleUnchecked() {
// Mark the message as in use while it remains in the recycled object pool.
// Clear out all other details.
flags = FLAG_IN_USE;
what = 0;
arg1 = 0;
arg2 = 0;
obj = null;
replyTo = null;
sendingUid = -1;
when = 0;
target = null;
callback = null;
data = null;
synchronized (sPoolSync) {
if (sPoolSize < MAX_POOL_SIZE) {
next = sPool;
sPool = this;
sPoolSize++;
}
}
}
获取消息代码片段:
AsyncQueryHandler.WorkerHandler也继承自Handler 非UI线程操作处理类 在该类执行增删改操作
HandlerThread 独立线程的Loop管理类
工作流程如下:
1.创建AsyncQueryHandler实例会同时创建工作线程Handler
/**
* Return a new Message instance from the global pool. Allows us to
* avoid allocating new objects in many cases.
*/
public static Message obtain() {
synchronized (sPoolSync) {
if (sPool != null) {
Message m = sPool;
sPool = m.next;
m.next = null;
m.flags = 0; // clear in-use flag
sPoolSize--;
return m;
}
}
return new Message();
}
池最大为50条消息,即链表长度最多可回收50条消息
private static final int MAX_POOL_SIZE = 50;
分隔线/
后来我又发现了AsyncQueryHandler 什么鬼?
查看源码发现AsyncQueryHandler主要做了一个异步操作数据(ContextProvider)的架构.
AsyncQueryHandler继承自Handler handMessage处理是否在自线程与Handler一样取决于构造该对象时所在线程
public AsyncQueryHandler(ContentResolver cr) {
super();
//弱引用Resolver对象
mResolver = new WeakReference<ContentResolver>(cr);
synchronized (AsyncQueryHandler.class) {
if (sLooper == null) {
//HandlerThread负责创建一个线程并生成loop
HandlerThread thread = new HandlerThread("AsyncQueryWorker");
thread.start();
sLooper = thread.getLooper();
}
}
//获取HandlerThread生成的loop 因为在自线程所以mWorkeThreadHandler工作在自线程
mWorkerThreadHandler = createHandler(sLooper);
}
2.HandlerThread 启动线程并创建loop HandlerThread是继承Thread的
@Override
public void run() {
mTid = Process.myTid();
Looper.prepare();
synchronized (this) {
mLooper = Looper.myLooper();
notifyAll();
}
Process.setThreadPriority(mPriority);
onLooperPrepared();
Looper.loop();
mTid = -1;
}
3.发生查询或者其他插入操作请求到工作线程
public final void startInsert(int token, Object cookie, Uri uri,
ContentValues initialValues) {
// Use the token as what so cancelOperations works properly
Message msg = mWorkerThreadHandler.obtainMessage(token);
msg.arg1 = EVENT_ARG_INSERT;
WorkerArgs args = new WorkerArgs();
//处理者设置为自己
args.handler = this;
args.uri = uri;
args.cookie = cookie;
args.values = initialValues;
msg.obj = args;
//发消息到工作线程
mWorkerThreadHandler.sendMessage(msg);
}
4.工作线程处理操作请求并将处理结果返回给AsyncQueryHandler(一般为UI线程中)
if (resolver == null) return;
WorkerArgs args = (WorkerArgs) msg.obj;
int token = msg.what;
int event = msg.arg1;
switch (event) {
case EVENT_ARG_QUERY:
cursor = resolver.query(args.uri, args.projection,
args.selection, args.selectionArgs,
args.orderBy);
args.result = cursor;
break;
Message reply = args.handler.obtainMessage(token);
reply.obj = args;
reply.arg1 = msg.arg1;
reply.sendToTarget();
//将结果发消息回AsyncQueryHandler
protected class WorkerHandler extends Handler {
public WorkerHandler(Looper looper) {
super(looper);
}
@Override
public void handleMessage(Message msg) {
//获取弱引用对象 这样AsyncQueryHandler被销毁后 不会一直引用着防止内存泄漏
final ContentResolver resolver = mResolver.get();