Looper

作者: 画十 | 来源:发表于2017-05-22 19:04 被阅读23次

    Before:

    Looper中用到ThreadLocal以及MessageQueue,不熟悉的可以先简单了解下;

    Android开发中时常遇到一下错误:

    java.lang.RuntimeException: Can't create handler inside thread that has not called Looper.prepare()
    

    下面就来了解下Looper这个类:

    public final class Looper {
        //显然,在不同线程会存有互不干扰的Looper实例
        static final ThreadLocal<Looper> sThreadLocal = new ThreadLocal<>();
       
        private static void prepare(boolean quitAllowed) {
            if (sThreadLocal.get() != null) {
                throw new RuntimeException("Only one Looper may be created per thread");
            }
            sThreadLocal.set(new android.os.Looper(quitAllowed));
        }
    
        public static void loop() {
            final android.os.Looper me = myLooper();
            if (me == null) {
                throw new RuntimeException("No Looper; Looper.prepare() wasn't called on this thread.");
            }
            final MessageQueue queue = me.mQueue;
        
            for (;;) {
                Message msg = queue.next(); // 若没有消息则阻塞在这里
                if (msg == null) {
                    return;
                }
    
                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);
                    }
                }
                msg.recycleUnchecked();
            }
        }
        
        public static @Nullable Looper myLooper() {
            return sThreadLocal.get();
        }
    }
    
    分析
    • 先讲2个故事:

    故事1:小明没有零花钱了,又不敢向爸爸妈妈,就想起了他奶奶。他奶奶家和他家距离不远也就几百米,于是他就到他奶奶家去了,但是小明奶奶家里没有现金了,而奶奶又年纪大了不方便去取钱,就打电话给银行要求银行送钱上门,但是银行工作人员办事效率不高,半天都没有送来,于是着急的小明只能空手而返了;过了一会他又去奶奶家看钱有没有送过来,结果银行工作人员还没有过来,小明只能再次空手而返......就这样不断来来回回去奶奶家看钱有没有送过来;
    故事2:小红和小明一样没有零花钱却又不敢向爸爸妈妈要,也去找奶奶要;小红第一次去奶奶家,奶奶发现家里没有现金了,就打电话给银行要求送钱上门,而小红则陪着奶奶在家里等银行工作人员送前上门,奶奶心疼小红,不断打电话催银行快点快点;就这样小红每次去奶奶家要零花钱都是等拿到钱了再离开;

    • 暂且不管上述故事剧情如何,其中小明是不管奶奶在不在家,去了就回来,有钱就拿钱,没钱就空手回家,而小红是去了就拿到钱才回来;回到Looper上来,loop方法就像是小红,而奶奶则是MessageQueueloop方法调用MessageQueuenext方法,若next方法没有东西可返回就一直等着,并且不断询问有没有新消息过来;

    • 要在新线程中使用Looper,需要初始化Looper,因为Looper对象是保存在ThreadLocal上的,所以在每个线程上都需要重新初始化,并且不能重复初始化;

    • 开启消息循环需要调用Looper.loop();,结束时候别忘了要Looper.myLooper().quit();退出轮询;

    相关文章

      网友评论

          本文标题:Looper

          本文链接:https://www.haomeiwen.com/subject/oxdixxtx.html