//可以看到我们的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

实现线程间通信的

Looper 源码分析的更多相关文章

  1. 【Android】Handler、Looper源码分析

    一.前言 源码分析使用的版本是 4.4.2_r1. Handler和Looper的入门知识以及讲解可以参考我的另外一篇博客:Android Handler机制 简单而言:Handler和Looper是 ...

  2. Handle/Looper源码分析;

    1. Handle中的属性: final Looper mLooper; final MessageQueue mQueue; final Callback mCallback; final bool ...

  3. Handler、Looper、MessageQueue、Thread源码分析

    关于这几个之间的关系以及源码分析的文章应该挺多的了,不过既然学习了,还是觉得整理下,印象更深刻点,嗯,如果有错误的地方欢迎反馈. 转载请注明出处:http://www.cnblogs.com/John ...

  4. Android Handler处理机制 ( 一 )(图+源码分析)——Handler,Message,Looper,MessageQueue

    android的消息处理机制(图+源码分析)——Looper,Handler,Message 作为一个大三的预备程序员,我学习android的一大乐趣是可以通过源码学习 google大牛们的设计思想. ...

  5. Android源码分析-消息队列和Looper

    转载请注明出处:http://blog.csdn.net/singwhatiwanna/article/details/17361775 前言 上周对Android中的事件派发机制进行了分析,这次博主 ...

  6. Android消息机制源码分析

    本篇主要介绍Android中的消息机制,即Looper.Handler是如何协同工作的: Looper:主要用来管理当前线程的消息队列,每个线程只能有一个Looper Handler:用来将消息(Me ...

  7. Android7.0 Phone应用源码分析(二) phone来电流程分析

    接上篇博文:Android7.0 Phone应用源码分析(一) phone拨号流程分析 今天我们再来分析下Android7.0 的phone的来电流程 1.1TelephonyFramework 当有 ...

  8. Robotium源码分析之Instrumentation进阶-attach

    在分析Robotium的运行原理之前,我们有必要先搞清楚Instrumentation的一些相关知识点,因为Robotium就是基于Instrumentation而开发出来的一套自动化测试框架.鉴于之 ...

  9. Robotium源码分析之Instrumentation进阶

    在分析Robotium的运行原理之前,我们有必要先搞清楚Instrumentation的一些相关知识点,因为Robotium就是基于Instrumentation而开发出来的一套自动化测试框架.鉴于之 ...

  10. Android7.0 Phone应用源码分析(三) phone拒接流程分析

    本文主要分析Android拒接电话的流程,下面先来看一下拒接电话流程时序图 步骤1:滑动按钮到拒接图标,会调用到AnswerFragment的onDecline方法 com.android.incal ...

随机推荐

  1. 2003031126-石升福-Python数据分析-五一假期作业

    项目 内容 班级链接 20级数据班(本) 作业链接 五一假期作业 博客名称 2003031126-石升福-Python数据分析-五一假期作业 要求 每道题要有题目,代码(使用插入代码,不会插入代码的自 ...

  2. Hspui的使用,NJUPT

    一.打开Hspui,进入UI界面 二.添加.sp文件 File->Open打开想要仿真的文件 三.运行仿真 点击Simulate 四.观察结果 点击Waveview进入波形观察器 选中目录下要观 ...

  3. Windows10常用快捷键总结

    --Windows10常用快捷键总结 1. Window键: 打开或关闭|开始菜单 2. Win + A 打开操作中心 3. Win + D 显示桌面 4. Win + E 打开计算机文件管理器 5. ...

  4. 1004 Counting Leaves (30分)

    今天在热心网友的督促下完成了第一道PAT编程题. 太久没有保持训练了,整个人都很懵. 解题方法: 1.读懂题意 2.分析重点 3.确定算法 4.代码实现 该题需要计算每层的叶子节点个数,所以选用BFS ...

  5. Angular Material TreeTable Component 使用教程

    一. 安装 npm i ng-material-treetable --save npm i @angular/material @angular/cdk @angular/animations -- ...

  6. PYinstall打包程序出现编码错误的解决 'utf-8' codec can't decode byte 0xce in position 171: invalid continuation b

    网上说,先执行,再打包 chcp 65001 试过没有用. 解决方案: 把import的包批量注释,然后寻找是import那个文件导致. 虽然注释会导致程序运行出错,但是打包才不管你能不能运行. 最后 ...

  7. mock数据规则

    Mock数据规则 随机生成100条内的list数据 let Mock = require("mockjs"); let basicData = Mock.mock({ " ...

  8. Qt非主线程显示窗口的简易思路

    首发于我的个人博客:xie-kang.com 博客内有更多文章,欢迎大家访问 原文地址 Qt 在非主线程是无法显示UI窗口的,如果我们在其它线程中处理完数据,需要使用窗口展示,或者在其它线程需要使用到 ...

  9. 适用于 Linux 的 Windows 子系统使用 Visual Studio Code

    在WSL中使用VS Code,先在Windows中安装vscode,再通过功能扩展安装Vscode for wsl. VSCode 有system和user两个版本,默认下载链接为user版本.以下内 ...

  10. Python学习笔记--循环的知识以及应用

    while循环 代码: 结果: 案例:求1-100的和 实现: 案例:while循环猜数字 实现: while循环的嵌套使用 案例:打印九九乘法表 (注意:要是想要输出不换行,代码可以这样写:prin ...