一。总结

Looper有一个MessageQueue,用于封装消息循环。   Handler封装了消息投递,消息处理等的辅助类

二。分析

1.从Looper的用法开始分析

 class LooperThread extends Thread {
public Handler mHandler;
public void run() {
Looper.prepare(); //(1)调用prepare
mHandler = new Handler() {
public void handleMessage(Message msg) {
// process incoming messages here
}
};
Looper.loop(); //(2)进入消息循环
}
}

(11)prepare做了什么?

static final ThreadLocal<Looper> sThreadLocal = new ThreadLocal<Looper>();
public static void prepare() {
    if (sThreadLocal.get() != null) {
throw new RuntimeException("Only one Looper may be created per thread");
}
    sThreadLocal.set(new Looper()); //(12)构造一个Looper,设置到线程本地变量中
 } 

(12)构造Looper对象

    private Looper() {
mQueue = new MessageQueue(quitAllowed);
mRun = true;
mThread = Thread.currentThread(); //得到当前线程
}

所以由(12)可知,prepare把Looper对象保存在线程本地变量中。巧妙地把Looper和调用线程关联起来。

2.Handler-MessageQueue-Looper,三者构成了死循环+消息通信的模型

    public static void loop() {
final Looper me = myLooper(); // (21)取得线程本地变量Looper
if (me == null) {
throw new RuntimeException("No Looper; Looper.prepare() wasn't called on this thread.");
}
final MessageQueue queue = me.mQueue; // 取出Looper中的queue // 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); //Handler target; 参照下面的dispatchMessage方法 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.recycle();
}
}
public static Looper myLooper() { //(22)返回线程本地变量Looper
return sThreadLocal.get();
}

所以由(21)、(22)可看出loop()处理本线程消息队列中的消息。

三。Looper, Message,Handler之间的关系

1.Message中有个Handler,指定这个Message由哪个Handler处理

Handler target;    

2.分析Handler成员变量

    final MessageQueue mQueue;
final Looper mLooper;
final Callback mCallback;

3.Handler默认构造函数

  public Handler() {
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());
}
} mLooper = Looper.myLooper(); //(31)获得调用线程的Looper
if (mLooper == null) {
throw new RuntimeException( "Can't create handler inside thread that has not called Looper.prepare()");
}
mQueue = mLooper.mQueue;    //(32)获得Looper中的消息队列
mCallback = null;
}

4.Handler的另一个构造函数

public Handler(Looper looper) {          //(33)传入某个线程的Looper
mLooper = looper;
mQueue = looper.mQueue;      //(34)获得Looper中的消息队列
        mCallback = null;
}

由上可知,Handler中的MessageQueue都会指向Looper中的消息队列。

5.There are two main uses for a Handler:

   (1) to schedule messages and runnables to be executed as some point in the future;

  (2) to enqueue an action to be performed on a different thread than your own.

   Handler只有一个消息队列,即MessageQueue。通过post()传进去的Runnable将会被封装成消息对象后传入MessageQueue。当Looper轮询到该线程时,并不会单独开启一个新线程,

而Runnable仍然在当前Looper绑定的线程中执行,Handler只是调用了该线程对象的run()而已。通过post()将Runnable提交到主线程的Looper中可以实现UI的更新。

51.sendMessage

    public boolean sendMessageAtTime(Message msg, long uptimeMillis){
boolean sent = false;
MessageQueue queue = mQueue;
if (queue != null) {
msg.target = this;        //(41)把处理这个message的Handler设为自己
sent = queue.enqueueMessage(msg, uptimeMillis);
}
else {
RuntimeException e = new RuntimeException( this + " sendMessageAtTime() called with no mQueue");
Log.w("Looper", e.getMessage(), e);
}
return sent;
}

2.post

    public final boolean post(Runnable r){
return sendMessageDelayed(getPostMessage(r), 0);        
} private static Message getPostMessage(Runnable r) {
Message m = Message.obtain();
m.callback = r;                          ///*package */ Runnable callback; 将Runnable封装成消息对象
return m;
}
public final boolean sendMessageDelayed(Message msg, long delayMillis){
if (delayMillis < 0) {
delayMillis = 0;
}
return sendMessageAtTime(msg, SystemClock.uptimeMillis() + delayMillis);
}

6.消息处理

    public void handleMessage(Message msg) {   //子类要重写的方法
} public void dispatchMessage(Message msg) {
if (msg.callback != null) {      //如果msg本身有callback
handleCallback(msg);
} else {
if (mCallback != null) {        //如果handler本身有callback
if (mCallback.handleMessage(msg)) {
return;
}
}
handleMessage(msg);            //最后交给子类处理
}
}

7.msg的Callback

    private static void handleCallback(Message message) {
message.callback.run(); //直接调用Runnable的run方法,也就是说不是新建线程来执行
}

android(七)Looper Handler分析的更多相关文章

  1. Android的消息循环机制 Looper Handler类分析

    Android的消息循环机制 Looper Handler类分析 Looper类说明   Looper 类用来为一个线程跑一个消息循环. 线程在默认情况下是没有消息循环与之关联的,Thread类在ru ...

  2. 转 Android的消息处理机制(图+源码分析)——Looper,Handler,Message

    作为一个大三的预备程序员,我学习android的一大乐趣是可以通过源码学习google大牛们的设计思想.android源码中包含了大量的设计模式,除此以外,android sdk还精心为我们设计了各种 ...

  3. 【转】android的消息处理机制(图+源码分析)——Looper,Handler,Message

    原文地址:http://www.cnblogs.com/codingmyworld/archive/2011/09/12/2174255.html#!comments 作为一个大三的预备程序员,我学习 ...

  4. android的消息处理机制(图+源码分析)——Looper,Handler,Message

    android源码中包含了大量的设计模式,除此以外,android sdk还精心为我们设计了各种helper类,对于和我一样渴望水平得到进阶的人来说,都太值得一读了.这不,前几天为了了解android ...

  5. android的消息处理机制(图文+源码分析)—Looper/Handler/Message[转]

    from:http://www.jb51.net/article/33514.htm 作为一个大三的预备程序员,我学习android的一大乐趣是可以通过源码学习google大牛们的设计思想.andro ...

  6. Android -- 消息处理机制源码分析(Looper,Handler,Message)

    android的消息处理有三个核心类:Looper,Handler和Message.其实还有一个Message Queue(消息队列),但是MQ被封装到Looper里面了,我们不会直接与MQ打交道,因 ...

  7. android的消息处理机制——Looper,Handler,Message

    在开始讨论android的消息处理机制前,先来谈谈一些基本相关的术语. 通信的同步(Synchronous):指向客户端发送请求后,必须要在服务端有回应后客户端才继续发送其它的请求,所以这时所有请求将 ...

  8. (转)Android消息处理机制(Handler、Looper、MessageQueue与Message)

    转自 http://www.cnblogs.com/angeldevil/p/3340644.html Android消息处理机制(Handler.Looper.MessageQueue与Messag ...

  9. android的消息处理有三个核心类:Looper,Handler和Message。

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

随机推荐

  1. Memcached 数据导出与导入

    我们使用 memcached-tool 命令来导出数据: [root@localhost ~]# memcached-tool dump > /tmp/.txt Dumping memcache ...

  2. 使用 urllib 分析 Robots 协议

    (1) Robots Exclusion Protocol,网络爬虫排除标准,也称爬虫协议.机器人协议,用来告诉爬虫和搜索引擎哪些页面可以抓取,哪些不可以抓取(2) Robots 协议以 robots ...

  3. Unity绘制Png图片

    using System.Collections; using System.Collections.Generic; using System.IO; using UnityEngine; publ ...

  4. AngularJS的表达式、指令的学习(2)

    最近没有那么忙,就来系统学习一下AngularJS吧,昨天简单的认识了一下,今天就从表达式入手吧,嘿嘿. 一.AngularJS 表达式 AngularJS表达式写在双大括号内:{{expressio ...

  5. g++参数介绍

    转自http://www.cnblogs.com/lidan/archive/2011/05/25/2239517.html [介绍] gcc and g++分别是gnu的c & c++编译器 ...

  6. 设置ADB网络连接目标板

    adb connect 网络连接目标板报错,原因参考[http://ytydyd.blog.sohu.com/146260552.html].而且指定 adb connect <IP>:5 ...

  7. FileReader类和FileWriter类的基本用法示例

    package com.example.io; import java.io.File; import java.io.FileReader; import java.io.FileWriter; i ...

  8. SqlServer 连接远程服务器数据库 实现跨服务器联合查询

    第一种: exec sp_addlinkedserver 'ITSV ', ' ', 'SQLOLEDB ', '远程服务器名或ip地址 ' exec sp_addlinkedsrvlogin 'IT ...

  9. LESS CSS 框架简介与使用

    简介 CSS(层叠样式表)是一门历史悠久的标记性语言,同 HTML 一道,被广泛应用于万维网(World Wide Web)中.HTML 主要负责文档结构的定义,CSS 负责文档表现形式或样式的定义. ...

  10. 【Spring源码分析系列】bean的加载

    前言 以 BeanFactory bf  = new XmlBeanFactory(new ClassPathResource("beans.xml"));为例查看bean的加载过 ...