博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
android源码分析-深入looper handler message
阅读量:5865 次
发布时间:2019-06-19

本文共 8545 字,大约阅读时间需要 28 分钟。

本来是不想写这篇文章的,但是很早以前看过的东西容易遗忘,希望还是给自己一个记录吧,另外此篇希望能够写的深入一些。

looper是什么就不介绍了吧,一个线程的消息泵,handler是消息的操作者,messagequeue是消息队列。
我们从源头开始看起,activity里的主ui线程就是ActivityThread mMainThread。这个ActivityThread的main函数会在程序创建的时候被调用,那么看下内部:

public static void main(String[] args) {        Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "ActivityThreadMain");        SamplingProfilerIntegration.start();        // CloseGuard defaults to true and can be quite spammy.  We        // disable it here, but selectively enable it later (via        // StrictMode) on debug builds, but using DropBox, not logs.        CloseGuard.setEnabled(false);        Environment.initForCurrentUser();        // Set the reporter for event logging in libcore        EventLogger.setReporter(new EventLoggingReporter());        // Make sure TrustedCertificateStore looks in the right place for CA certificates        final File configDir = Environment.getUserConfigDirectory(UserHandle.myUserId());        TrustedCertificateStore.setDefaultUserDirectory(configDir);        Process.setArgV0("
"); Looper.prepareMainLooper(); ActivityThread thread = new ActivityThread(); thread.attach(false); if (sMainThreadHandler == null) { sMainThreadHandler = thread.getHandler(); } if (false) { Looper.myLooper().setMessageLogging(new LogPrinter(Log.DEBUG, "ActivityThread")); } // End of event ActivityThreadMain. Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER); Looper.loop(); throw new RuntimeException("Main thread loop unexpectedly exited"); }

首先走了Looper.prepareMainLooper();这个是与普通线程创建looper不同的地方,普通的都是prepare方法调用。那么看看里面:

public static void prepareMainLooper() {        prepare(false);        synchronized (Looper.class) {            if (sMainLooper != null) {                throw new IllegalStateException("The main Looper has already been prepared.");            }            sMainLooper = myLooper();        }    }

还是prepare,但是传递的参数是false。在这里表示的是不允许退出。再来就是prepare:

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。同时可以看到,如果已经存在了这个线程本地对象,那么直接报错,也就是说一个线程只允许一个looper存在。

回到ActivityThread的main,初始化好之后就是sMainThreadHandler = thread.getHandler();这个getHandler里直接返回的是mH,其实就是一个Handler的子类H。这个H是个很长的类,就是定义好的对activity默认相应的各项。
这之后会调用到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;        // 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.isTagEnabled(traceTag)) {                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();        }    }

首先看到在Looper的构造函数里就创建了MessageQueue:

private Looper(boolean quitAllowed) {        mQueue = new MessageQueue(quitAllowed);        mThread = Thread.currentThread();    }

那么这个loop函数中就直接取过来用,后面是个死循环,不断的通过queue.next()获取新的消息,并最终调用msg.target.dispatchMessage(msg);来处理。至此looper分析完了。下面看看Message的msg.target.dispatchMessage(msg);是怎么调用的:

看到message的时候,他的target就是Handler。这下子串上了吧,在looper的loop函数循环中枚举新message,并交给message里的Handler的dispatchMessage函数处理。那么好吧,我们回顾下,在发送message的时候,一般先obtain获取一个消息,我们看看:

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

看起来像链表是吧,每次取得时候将sPool给m,sPool移动到下一个,然后将sPoolSize减一,最后返回m。再看下回收部分:

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

这里将自己赋值给sPool,然后sPoolSize++,看到这里应当明白,其实就是个链表的应用,保证sPool指向的是空闲的message的第一个。

然后呢,应用的时候会调用Handler的sendMessage函数,并且将参数设置为刚才获取到的空闲message,对吧。那么我们看看这个sendMessage,最终会调用到sendMessageAtTime中:

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

这里出现了MessageQueue,然后会走到enqueueMessage:

private boolean enqueueMessage(MessageQueue queue, Message msg, long uptimeMillis) {        msg.target = this;        if (mAsynchronous) {            msg.setAsynchronous(true);        }        return queue.enqueueMessage(msg, uptimeMillis);    }

第一句就是msg.target = this;,清楚了吧,这里将message的target赋值为handler自身。那么回到loop这个函数中,会走到msg.target.dispatchMessage(msg);这句话,实际上就是在走handler的msg.target.dispatchMessage。再进入到handler中看看这个dispatchMessage:

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

能看到什么?先试图调用message的callback,如果没有则试图调用自身的mCallback的handleMessage,如果还没有,好吧,直接走handleMessage。依次看一下,首先是handleCallback:

private static void handleCallback(Message message) {        message.callback.run();    }

这个callback是个什么呢?可以通过Message的obtain看到:

public static Message obtain(Handler h, Runnable callback) {        Message m = obtain();        m.target = h;        m.callback = callback;        return m;    }

一个runnable,那么这个runnable是何时被赋值的呢?看Handler中:

public final boolean post(Runnable r)    {       return  sendMessageDelayed(getPostMessage(r), 0);    }

看到了吧,这里在执行post的时候给的runnable就是这个callback。那么再想想,我们在写代码的时候,很多时候都会走一个handler的post或者postDelayed,执行一段代码在主线程中,这个传递进来的runnable就是message的callback了。顺便说下,View里的post也是调用的这个东西。

下面是Handler自身的mCallback了,在构造Handler的时候可以指定一个callback传递进来,这个Callback是这样定义的:

public interface Callback {        public boolean handleMessage(Message msg);    }

指定的话就会走这个标准的回调,否则最后会走Handler的handleMessage,这个才是我们最常用的继承下来的函数。看到了吧,由于loop函数运行在主线程中,因此以上这些都是在主线程中运行的代码。注意,这3个是排他性的,如果前面的可以执行就不会走后面的。

现在比较清楚了吧,整个消息循环是如何运转的。

转载地址:http://feynx.baihongyu.com/

你可能感兴趣的文章
Iframe高度自适应
查看>>
分享一个导出Excel时页面不跳转的小技巧
查看>>
VC内存溢出一例 –- 调用约定不一致
查看>>
消息队列性能对比
查看>>
CART:分类与回归树
查看>>
Django1.9 Python3.4出现Error loading MySQLdb
查看>>
在Express和Socket.IO中使用session
查看>>
es6 - filter for-chrome
查看>>
Centos下安装破解confluence6.3的操作记录
查看>>
PyCharm安装第三方库如Requests
查看>>
给你一天时间,你会从最懂钱的这些人身上学点啥?
查看>>
一本CTO开源的工程师职业发展规划指南
查看>>
福利丨所有AI安全的讲座里,这可能是最实用的一场
查看>>
滴滴春节前裁员:内部人士称是重组人才体系 末尾淘汰
查看>>
IT基础架构又有新概念?可组合基础设施是什么?
查看>>
万科创始人王石出任华大基因联席董事长 协助汪建管理
查看>>
西藏林芝边境小康村迎藏历新年
查看>>
普悠玛号将开放卖站票 台铁局:安全测试报告合格
查看>>
广东法院公开裁判文书超350万份
查看>>
福建宁德自闭症儿童家长:有爱,我们不孤独
查看>>