zoukankan      html  css  js  c++  java
  • Looper 源码分析

     
     
        //可以看到我们的Looper是存放在线程独有的ThreadLocal进行隔离的
        //也就是每个线程独有一份Looper
        static final ThreadLocal<Looper> sThreadLocal = new ThreadLocal<Looper>();
        //系统帮我们实现的主线程的Looper对象
        private static Looper sMainLooper;
        //每一个Looper都有自己的MessageQueue消息队列
        final MessageQueue mQueue;
        final Thread mThread;
        
      *  class LooperThread extends Thread {
      *      public Handler mHandler;
      *
      *      public void run() {
      *          Looper.prepare();
      *
      *          mHandler = new Handler() {
      *              public void handleMessage(Message msg) {
      *                  // process incoming messages here
      *              }
      *          };
      *
      *          Looper.loop();
      *      }
      *  }
      这个是Looper开篇的使用示例
      我们在使用Handler机制的时候需要创建一个Looper对象利用Looper里面的MessageQueue消息队列
      来存放我们发送的Message消息Message消息里面存有我们发送的数据、延迟时间、回调方法等。
      这样在looper进行轮询消息队列的时候就能够将里面的Message交给对应的Handler去处理。
     
      在子线程中:
      Looper.prepare();是用来创建一个Looper的
      源码:
          public static void prepare() {
            prepare(true);
        }

        private static void prepare(boolean quitAllowed) {
            //从ThreadLocal去拿我们的Looper 如果已经存在了就抛出异常
            if (sThreadLocal.get() != null) {
                throw new RuntimeException("Only one Looper may be created per thread");
            }
            //否则就创建一个looper对象并放在ThreadLocal中存储
            sThreadLocal.set(new Looper(quitAllowed));
        }
       new Looper(quitAllowed)    源码:
       
        private Looper(boolean quitAllowed) {
            mQueue = new MessageQueue(quitAllowed);
            mThread = Thread.currentThread();
        }
      可以看到    在创建Looper的时候也会创建一个MessageQueue消息队列
         
         //主线程的Looper创建----系统会在ActivityThread的main()方法里面调用这个方法进行创建的
         public static void prepareMainLooper() {
            prepare(false);
            synchronized (Looper.class) {
                if (sMainLooper != null) {
                    throw new IllegalStateException("The main Looper has already been prepared.");
                }
                sMainLooper = myLooper();
            }
        }
        
            * 源码分析:main()
            **/
            public static void main(String[] args) {
            

                Looper.prepareMainLooper();
                // 1. 为主线程创建1个Looper对象,同时生成1个消息队列对象(MessageQueue)
                // 方法逻辑类似Looper.prepare()
                // 注:prepare():为子线程中创建1个Looper对象
                
                
                ActivityThread thread = new ActivityThread();
                // 2. 创建主线程

                Looper.loop();
                // 3. 自动开启 消息循环 ->>下面将详细分析

            }    
        
            loop()    源码
        
            public static void loop() {
            //获取当前线程的Looper对象
            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();

            // Allow overriding a threshold with a system prop. e.g.
            // adb shell 'setprop log.looper.1000.main.slow 1 && stop && start'
            final int thresholdOverride =
                    SystemProperties.getInt("log.looper."
                            + Process.myUid() + "."
                            + Thread.currentThread().getName()
                            + ".slow", 0);

            boolean slowDeliveryDetected = false;

            for (;;) {
            // 从MessageqQueue里面去拿消息 这个过程会随着message取完后阻塞
                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;
                long slowDispatchThresholdMs = me.mSlowDispatchThresholdMs;
                long slowDeliveryThresholdMs = me.mSlowDeliveryThresholdMs;
                if (thresholdOverride > 0) {
                    slowDispatchThresholdMs = thresholdOverride;
                    slowDeliveryThresholdMs = thresholdOverride;
                }
                final boolean logSlowDelivery = (slowDeliveryThresholdMs > 0) && (msg.when > 0);
                final boolean logSlowDispatch = (slowDispatchThresholdMs > 0);

                final boolean needStartTime = logSlowDelivery || logSlowDispatch;
                final boolean needEndTime = logSlowDispatch;

                if (traceTag != 0 && Trace.isTagEnabled(traceTag)) {
                    Trace.traceBegin(traceTag, msg.target.getTraceName(msg));
                }

                final long dispatchStart = needStartTime ? SystemClock.uptimeMillis() : 0;
                final long dispatchEnd;
                try {
                    //取出的消息会交给对应的Handler去处理
                    msg.target.dispatchMessage(msg);
                    dispatchEnd = needEndTime ? SystemClock.uptimeMillis() : 0;
                } finally {
                    if (traceTag != 0) {
                        Trace.traceEnd(traceTag);
                    }
                }
                if (logSlowDelivery) {
                    if (slowDeliveryDetected) {
                        if ((dispatchStart - msg.when) <= 10) {
                            Slog.w(TAG, "Drained");
                            slowDeliveryDetected = false;
                        }
                    } else {
                        if (showSlowLog(slowDeliveryThresholdMs, msg.when, dispatchStart, "delivery",
                                msg)) {
                            // Once we write a slow delivery log, suppress until the queue drains.
                            slowDeliveryDetected = true;
                        }
                    }
                }
                if (logSlowDispatch) {
                    showSlowLog(slowDispatchThresholdMs, dispatchStart, dispatchEnd, "dispatch", 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();
            }
        }
        
      总结:Looper实际是利用ThreadLocal和线程进行绑定的,通过内部维护的一个消息队列来存储格格Handler发送过来的Message

     实现线程间通信的 
        
        
        
        
        
        
        
        
        
        
        
        
        
       

  • 相关阅读:
    Android防止按钮连续点击
    Android中的AlertDialog遇到的错误
    android通过Jni加载so库遇到UnsatisfiedLinkError问题!!!
    接口回调
    Android中的APinner2
    AndroidAPI
    Android中的下拉列表
    学习地址
    2018/12/21:Date类
    2018/12.21:找出数组最大项和最小项。
  • 原文地址:https://www.cnblogs.com/lianzhen/p/12926737.html
Copyright © 2011-2022 走看看