Handler,Looper,MessageQueue,Message总结

转载部分来自: http://gundumw100.iteye.com/blog/858233

转载部分对于应用层非常简洁明了

原创部分是基于Android4.4源代码,有什么错误或不足,欢迎指正

转载部分:

一、几个关键概念

1、MessageQueue:是一种 数据 结构,见名知义,就是一个消息队列,存放消息的地方。每一个线程最多只可以拥有一个MessageQueue数据结构。

创建一个线程的时候,并不会自动 创建其MessageQueue。通常使用一个Looper对象对该线程的MessageQueue进行管理。主线程创建时,会创建一个默认的Looper对象,而Looper对象的创建,将自动创建一个Message Queue。其他非主线程,不会自动创建Looper,要需要的时候,通过调用prepare函数来实现。

2、Message:消息对象,Message Queue中的存放的对象。一个Message Queue中包含多个Message。

Message实例对象的取得,通常使用Message类里的静态方法obtain(),该方法有多个重载版本可供选择;它的创建并不一定是直接创建一个新的实例,而是先从Message Pool(消息池)中看有没有可用的Message实例,存在则直接取出返回这个实例。如果Message Pool中没有可用的Message实例,则才用给定的参数创建一个Message对象。调用removeMessages()时,将Message从Message
Queue中删除,同时放入到Message Pool中。除了上面这种方式,也可以通过Handler对象的obtainMessage()获取 一个Message实例。

3、Looper:

是MessageQueue的管理者。每一个MessageQueue都不能脱离Looper而存在,Looper对象的创建是通过prepare函数来实现的。同时每一个Looper对象和一个线程关联。通过调用Looper.myLooper()可以获得当前线程的Looper对象

创建一个Looper对象时,会同时创建一个MessageQueue对象。除了主线程有默认的Looper,其他线程默认是没有MessageQueue对象的,所以,不能接受Message。如需要接受,自己定义 一个Looper对象(通过prepare函数),这样该线程就有了自己的Looper对象和MessageQueue数据结构了。

Looper从MessageQueue中取出Message然后,交由Handler的handleMessage进行处理。处理完成后,调用Message.recycle()将其放入Message Pool中。

4、Handler:

消息的处理者,handler 负责将需要传递的信息封装成Message,通过调用handler 对象的obtainMessage()来实现;

将消息传递给Looper,这是通过handler 对象的sendMessage()来实现的。继而由Looper将Message放入MessageQueue中。

当Looper对象看到MessageQueue中含有Message,就将其广播出去。该handler 对象收到该消息后,调用相应的handler 对象的handleMessage()方法对其进行处理。

二、线程之间的消息如何进行传递

1、主线程给自己发送Message

Java代码  

  1. package test.message;
  2. import android .app .Activity;
  3. import android.os.Bundle;
  4. import android.os.Handler;
  5. import android.os.Looper;
  6. import android.os.Message;
  7. import android.view.View ;
  8. import android.widget.Button;
  9. import android.widget.TextView ;
  10. public class MainActivity extends Activity {
  11. private Button btnTest;
  12. private TextView textView;
  13. private Handler handler ;
  14. @Override
  15. public void onCreate(Bundle savedInstanceState) {
  16. super.onCreate(savedInstanceState);
  17. setContentView(R.layout.main);
  18. btnTest = (Button)this.findViewById(R.id.btn_01);
  19. textView = (TextView)this.findViewById(R.id.view_01);
  20. btnTest.setOnClickListener(new View.OnClickListener() {
  21. @Override
  22. public void onClick(View arg0) {
  23. Looper looper = Looper.getMainLooper(); //主线程的Looper对象
  24. //这里以主线程的Looper对象创建了handler ,
  25. //所以,这个handler 发送的Message会被传递给主线程的MessageQueue。
  26. handler = new MyHandler(looper);
  27. handler .removeMessages(0);
  28. //构建Message对象
  29. //第一个参数:是自己指定的message代号,方便在handler 选择性地接收
  30. //第二三个参数没有什么意义
  31. //第四个参数需要封装的对象
  32. Message msg = handler .obtainMessage(1,1,1,"主线程发消息了");
  33. handler .sendMessage(msg); //发送消息
  34. }
  35. });
  36. }
  37. class MyHandler extends Handler{
  38. public MyHandler(Looper looper){
  39. super(looper);
  40. }
  41. public void handleMessage(Message msg){
  42. super.handleMessage(msg);
  43. textView.setText("我是主线程的Handler,收到了消息:"+(String)msg.obj);
  44. }
  45. }
  46. }

2、其他线程给主线程发送Message

Java代码  

  1. package test.message;
  2. import android.app.Activity;
  3. import android.os.Bundle;
  4. import android.os.Handler;
  5. import android.os.Looper;
  6. import android.os.Message;
  7. import android.view.View;
  8. import android.widget.Button;
  9. import android.widget.TextView;
  10. public class MainActivity extends Activity {
  11. private Button btnTest;
  12. private TextView textView;
  13. private Handler handler ;
  14. @Override
  15. public void onCreate(Bundle savedInstanceState) {
  16. super.onCreate(savedInstanceState);
  17. setContentView(R.layout.main);
  18. btnTest = (Button)this.findViewById(R.id.btn_01);
  19. textView = (TextView)this.findViewById(R.id.view_01);
  20. btnTest.setOnClickListener(new View.OnClickListener() {
  21. @Override
  22. public void onClick(View arg0) {
  23. //可以看出这里启动了一个线程来操作消息的封装和发送的工作
  24. //这样原来主线程的发送就变成了其他线程的发送,简单吧?呵呵
  25. new MyThread().start();
  26. }
  27. });
  28. }
  29. class MyHandler extends Handler{
  30. public MyHandler(Looper looper){
  31. super(looper);
  32. }
  33. public void handleMessage(Message msg){
  34. super.handleMessage(msg);
  35. textView.setText("我是主线程的Handler,收到了消息:"+(String)msg.obj);
  36. }
  37. }
  38. //加了一个线程类
  39. class MyThread extends Thread{
  40. public void run(){
  41. Looper looper = Looper.getMainLooper(); //主线程的Looper对象
  42. //这里以主线程的Looper对象创建了handler ,
  43. //所以,这个handler 发送的Message会被传递给主线程的MessageQueue。
  44. handler = new MyHandler(looper);
  45. //构建Message对象
  46. //第一个参数:是自己指定的message代号,方便在handler 选择性地接收
  47. //第二三个参数没有什么意义
  48. //第四个参数需要封装的对象
  49. Message msg = handler .obtainMessage(1,1,1,"其他线程发消息了");
  50. handler .sendMessage(msg); //发送消息
  51. }
  52. }
  53. }

3、主线程给其他线程发送Message

Java代码  

  1. package test.message;
  2. import android.app.Activity;
  3. import android.os.Bundle;
  4. import android.os.Handler;
  5. import android.os.Looper;
  6. import android.os.Message;
  7. import android.view.View;
  8. import android.widget.Button;
  9. import android.widget.TextView;
  10. public class MainActivity extends Activity {
  11. private Button btnTest;
  12. private TextView textView;
  13. private Handler handler ;
  14. @Override
  15. public void onCreate(Bundle savedInstanceState) {
  16. super.onCreate(savedInstanceState);
  17. setContentView(R.layout.main);
  18. btnTest = (Button)this.findViewById(R.id.btn_01);
  19. textView = (TextView)this.findViewById(R.id.view_01);
  20. //启动线程
  21. new MyThread().start();
  22. btnTest.setOnClickListener(new View.OnClickListener() {
  23. @Override
  24. public void onClick(View arg0) {
  25. //这里handler 的实例化在线程中
  26. //线程启动的时候就已经实例化了
  27. Message msg = handler .obtainMessage(1,1,1,"主线程发送的消息");
  28. handler .sendMessage(msg);
  29. }
  30. });
  31. }
  32. class MyHandler extends Handler{
  33. public MyHandler(Looper looper){
  34. super(looper);
  35. }
  36. public void handleMessage(Message msg){
  37. super.handleMessage(msg);
  38. textView.setText("我是主线程的Handler,收到了消息:"+(String)msg.obj);
  39. }
  40. }
  41. class MyThread extends Thread{
  42. public void run(){
  43. Looper.prepare(); //创建该线程的Looper对象,用于接收消息
  44. //注意了:这里的handler 是定义在主线程中的哦,呵呵,
  45. //前面看到直接使用了handler 对象,是不是在找,在什么地方实例化的呢?
  46. //现在看到了吧???呵呵,开始的时候实例化不了,因为该线程的Looper对象
  47. //还不存在呢。现在可以实例化了
  48. //这里Looper.myLooper()获得的就是该线程的Looper对象了
  49. handler = new ThreadHandler(Looper.myLooper());
  50. //这个方法,有疑惑吗?
  51. //其实就是一个循环,循环从MessageQueue中取消息。
  52. //不经常去看看,你怎么知道你有新消息呢???
  53. Looper.loop();
  54. }
  55. //定义线程类中的消息处理类
  56. class ThreadHandler extends Handler{
  57. public ThreadHandler(Looper looper){
  58. super(looper);
  59. }
  60. public void handleMessage(Message msg){
  61. //这里对该线程中的MessageQueue中的Message进行处理
  62. //这里我们再返回给主线程一个消息
  63. handler = new MyHandler(Looper.getMainLooper());
  64. Message msg2 = handler .obtainMessage(1,1,1,"子线程收到:"+(String)msg.obj);
  65. handler .sendMessage(msg2);
  66. }
  67. }
  68. }
  69. }

4、其他线程给自己发送Message

Java代码  

  1. package test.message;
  2. import android.app.Activity;
  3. import android.os.Bundle;
  4. import android.os.Handler;
  5. import android.os.Looper;
  6. import android.os.Message;
  7. import android.view.View;
  8. import android.widget.Button;
  9. import android.widget.TextView;
  10. public class MainActivity extends Activity {
  11. private Button btnTest;
  12. private TextView textView;
  13. private Handler handler ;
  14. @Override
  15. public void onCreate(Bundle savedInstanceState) {
  16. super.onCreate(savedInstanceState);
  17. setContentView(R.layout.main);
  18. btnTest = (Button)this.findViewById(R.id.btn_01);
  19. textView = (TextView)this.findViewById(R.id.view_01);
  20. btnTest.setOnClickListener(new View.OnClickListener() {
  21. @Override
  22. public void onClick(View arg0) {
  23. //启动线程
  24. new MyThread().start();
  25. }
  26. });
  27. }
  28. class MyHandler extends Handler{
  29. public MyHandler(Looper looper){
  30. super(looper);
  31. }
  32. public void handleMessage(Message msg){
  33. super.handleMessage(msg);
  34. textView.setText((String)msg.obj);
  35. }
  36. }
  37. class MyThread extends Thread{
  38. public void run(){
  39. Looper.prepare(); //创建该线程的Looper对象
  40. //这里Looper.myLooper()获得的就是该线程的Looper对象了
  41. handler = new ThreadHandler(Looper.myLooper());
  42. Message msg = handler .obtainMessage(1,1,1,"我自己");
  43. handler .sendMessage(msg);
  44. Looper.loop();
  45. }
  46. //定义线程类中的消息处理类
  47. class ThreadHandler extends Handler{
  48. public ThreadHandler(Looper looper){
  49. super(looper);
  50. }
  51. public void handleMessage(Message msg){
  52. //这里对该线程中的MessageQueue中的Message进行处理
  53. //这里我们再返回给主线程一个消息
  54. //加入判断看看是不是该线程自己发的信息
  55. if(msg.what == 1 && msg.obj.equals("我自己")){
  56. handler = new MyHandler(Looper.getMainLooper());
  57. Message msg2 = handler .obtainMessage(1,1,1,"禀告主线程:我收到了自己发给自己的Message");
  58. handler .sendMessage(msg2);
  59. }
  60. }
  61. }
  62. }
  63. }

附注:

上面四个例子的布局文件 是同一个文件main.xml

Xml代码  

  1. <?xml version="1.0" encoding="utf-8"?>
  2. <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
  3. android rientation="vertical"
  4. android:layout_width="fill_parent"
  5. android:layout_height="fill_parent"
  6. >
  7. <TextView  android:id="@+id/view_01"
  8. android:layout_width="fill_parent"
  9. android:layout_height="wrap_content"
  10. android:text="@string/hello "
  11. />
  12. <Button android:id="@+id/btn_01"
  13. android:layout_width="fill_parent"
  14. android:layout_height="wrap_content"
  15. android:text="测试消息" />
  16. </LinearLayout>

原创部分:

以PowerMangerService里的handler为例,说明一下handler具体实现过程

总的来说就是handler往MessageQueue里放消息,Looper.loop()从消息队列中读消息,调用handler对象的Handlemessage处理队列里的消息。

PowerManagerService.java:

public void init(Context context,LightsService ls,

ActivityManagerService am, BatteryService bs, IBatteryStats bss,

IAppOpsService appOps, DisplayManagerService dm) {

……

mHandlerThread = new HandlerThread(TAG);

mHandlerThread.start();

mHandler = newPowerManagerHandler(mHandlerThread.getLooper());

}

HandlerThread.java:

public HandlerThread(String name) {

super(name);

mPriority = Process.THREAD_PRIORITY_DEFAULT;

}

mHandlerThread.start();会调用此run函数

@Override

public void run() {

mTid = Process.myTid();

Looper.prepare();   \\会new  looper

synchronized (this) {

mLooper =Looper.myLooper();  \\获取上步new的looper

notifyAll();

}

Process.setThreadPriority(mPriority);

onLooperPrepared();

Looper.loop(); \\循环监视messageQueue

mTid = -1;

}

下面逐个分析run函数里的这几个方法:

public static void prepare() {

prepare(true);

}

private static void prepare(booleanquitAllowed) {

if (sThreadLocal.get() != null) {

throw newRuntimeException("Only one Looper may be created per thread");

}

sThreadLocal.set(new Looper(quitAllowed));
\\newlooper

}

private Looper(boolean quitAllowed) {

//new looper时候new出handler对应的MessageQueue

mQueue = new MessageQueue(quitAllowed);

mThread = Thread.currentThread();  //looper跟线程关联

}

-----------------------------------------------------

Looper.loop();

/**

* Run the message queue in this thread. Besure to call

* {@link #quit()} to end the loop.

*/

public static void loop() {

final Looper me = myLooper();

if (me == null) {

throw new RuntimeException("NoLooper; Looper.prepare() wasn‘t called on this thread.");

}

final MessageQueue queue = me.mQueue;

// Make sure the identity of thisthread is that of the local process,

// and keep track of what that identitytoken actually is.

Binder.clearCallingIdentity();

final long ident =Binder.clearCallingIdentity();

for (;;) {

Message msg = queue.next(); // mightblock//循环查看消息队列

if (msg == null) {

// No message indicates thatthe message queue is quitting.

return;

}

………

//messagequeue里有消息就会调到此方法  target为发送msg时候赋值的对应handler

msg.target.dispatchMessage(msg);

if (logging != null) {

logging.println("<<<<< Finished to " +msg.target + " " + msg.callback);

}

// Make sure that during the courseof dispatching the

// identity of the thread wasn‘tcorrupted.

final long newIdent =Binder.clearCallingIdentity();

if (ident != newIdent) {

Log.wtf(TAG, "Threadidentity 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();  //把这个msg实例放回到goable pool

}

}

Handler.java

/**

* Handle system messages here.

*/

public voiddispatchMessage(Message msg) {

if (msg.callback != null) {

handleCallback(msg);

} else {

if (mCallback != null) {

if (mCallback.handleMessage(msg)){

return;

}

}

handleMessage(msg);  \\这就是newhandler时候@override的handlemessage(msg)

}

}

/**

* Return a Message instance to the globalpool.  You MUST NOT touch

* the Message after calling this function-- it has effectively been

* freed.

*/

public void recycle() {

clearForRecycle();  //msg里信息清楚

synchronized (sPoolSync) {

if (sPoolSize < MAX_POOL_SIZE) {

next = sPool;

sPool = this;  添加到sPool里 message msg =  handler.obtain()就是从sPool里分配一个message对象

sPoolSize++;

}

}

}

创建和接收到此为止,下面说下handler怎么把msg发送到到MessageQueue里的

Handler.sendEmptyMessageAtTime(int what, longuptimeMillis)为例:

public final booleansendEmptyMessageAtTime(int what, long uptimeMillis) {

Message msg = Message.obtain();

msg.what = what;

returnsendMessageAtTime(msg, uptimeMillis);

}

public boolean sendMessageAtTime(Messagemsg, long uptimeMillis) {

//把handler对象的MessageQueue赋给queue

MessageQueuequeue = mQueue;

if (queue == null) {

RuntimeException e = newRuntimeException(

this + "sendMessageAtTime() called with no mQueue");

Log.w("Looper",e.getMessage(), e);

return false;

}

return enqueueMessage(queue, msg,uptimeMillis);

}

private boolean enqueueMessage(MessageQueuequeue, Message msg, long uptimeMillis) {

msg.target =this;  //上面再loop里用到的target赋值
this为当前handler对象

if (mAsynchronous) {

msg.setAsynchronous(true);

}

return queue.enqueueMessage(msg,uptimeMillis);  //MessageQueue.java里

}

MessageQueue.java:

booleanenqueueMessage(Message msg, long when) {

if (msg.isInUse()) {

throw newAndroidRuntimeException(msg + " This message is already in use.");

}

if (msg.target== null) {  //判断设置的target是否为NULL

throw newAndroidRuntimeException("Message must have a target.");

}

synchronized (this) {

if (mQuitting) {

RuntimeException e = newRuntimeException(

msg.target + " sending message toa Handler on a dead thread");

Log.w("MessageQueue",e.getMessage(), e);

return false;

}

msg.when = when;

Message p = mMessages; //mMessages为队列里最新的一个Message

boolean needWake;

if (p == null || when == 0 || when< p.when) {

// New head, wake up the eventqueue if blocked.

msg.next = p;

mMessages = msg;

needWake = mBlocked;

} else {

// Inserted within the middleof the queue.  Usually we don‘t have towake

// up the event queue unlessthere is a barrier at the head of the queue

// and the message is theearliest asynchronous message in the queue.

needWake = mBlocked &&p.target == null && msg.isAsynchronous();

Message prev;

//把msg加到MessageQueue里此函数执行完后再loop循环里就可以读取到此消息

for (;;) {

prev = p;

p = p.next;

if(p == null || when < p.when) {

break;

}

if(needWake && p.isAsynchronous()) {

needWake = false;

}

}

msg.next = p; // invariant: p == prev.next

prev.next = msg;

}

// We can assume mPtr != 0 becausemQuitting is false.

if (needWake) {

nativeWake(mPtr);

}

}

return true;

}

一个handler 只能对应一个Looper 一个MessageQueue

一个Thread  只能有一个Looper

New Handler()时候如果没有传入Looper默认用主线程的Looper作为此handler的Looper

时间: 2024-12-14 11:28:01

Handler,Looper,MessageQueue,Message总结的相关文章

Android多线程之图解Handler Looper MessageQueue Message

Android中的多线程可以有多种实现方式,前面我们已经讲过了封装程度较高异步任务(AnsyncTask),这一节我们来看看较为灵活的方式:Handler Looper MessageQueue Message. Message:用于线程之间传递信息,发送的消息放入目标线程的MessageQueue中. MessageQueue:用于简化线程之间的消息传递,MessageQueue接受发送端的Message,并作为消息处理端的输入源.每个线程只有一个实例. Handler:用于处理Message

转载:android笔记--android中的多线程--Handler, Looper, MessageQueue, Message类

什么时候使用多线程: 1. 耗时操作使用多线程, 耗时操作放在UI线程中会导致用户的操作无法得到响应. 2. 阻塞操作使用多线程, 理由同上. 3. 多核CUP的设备使用多线程, 可以有效提高CPU的利用率. 4. 并行操作使用多线程. android中的多线程模型主要涉及的类有:Looper, Handler, MessageQueue, Message等. 一:Looper类: 1 static final ThreadLocal<Looper> sThreadLocal = new Th

线程间通信: Handler , Looper, MessageQueue, Message (完结)

概述:    为了 线程间 通信方便, Handler 机制 通过 Handler 和 Looper, MessageQueue, Message 这些 类 之间的协作, 简化 多线程的开发.  线程的交互 会被封装 到 Message 中, 然后 通过 Handler 的方法 把 消息 放到 MessageQueue 消息队列中, 实现 Handler 机制的线程 都会 调用 Looper 的 loop() 方法, 则 Looper 作为 消息分发者的 作用就体现出来了.  loop() 方法

Android消息传递源码理解。Handler,Looper,MessageQueue,Message

Android中消息传递模块差不多看了好几次,虽然每次看的方式都差不多但是还是发觉的到每次看了之后,理解的更清晰一点. 关于这个模块的文章数不胜数,但是最重要的还是自己动手理解一遍更好. 会牵扯到的几个类: Handler.java  , Looper.java , MessageQueue.java , Message.java 源代码路径: xxx/frameworks/base/core/java/android/os  看的过程中你会发现高版本和低版本系统代码有些地方比较大的差距.从中我

Android中的Handler, Looper, MessageQueue和Thread

Android中的Handler, Looper, MessageQueue和Thread 前几天,和同事探讨了一下Android中的消息机制,探究了消息的发送和接收过程以及与线程之间的关系.虽然我们经常使用这些基础的东西,但对于其内部原理的了解,能使我们更加容易.合理地架构系统,并避免一些低级错误. 对于这部分的内容,将分成4小节来描述: 1.职责与关系 2.消息循环 3.线程与更新 4.几点小结 ------------------------------------------------

Android异步处理三:Handler+Looper+MessageQueue深入详解

Android Loop&Handle学习总结 - New Start - 博客频道 - CSDN.NET ?????? 昨晚偷懒,这篇博客只写了一个标题,今天早晨一看,还有15的阅读量.实在是对不起那些同学.......换了是我,也会BS这样的LZ吧!sorry 啦 -------------------------------------------------------------------------------------------------------------------

Android消息机制:Looper,MessageQueue,Message与handler

Android消息机制好多人都讲过,但是自己去翻源码的时候才能明白. 今天试着讲一下,因为目标是讲清楚整体逻辑,所以不追究细节. Message是消息机制的核心,所以从Message讲起. 1.Message是什么? 看一个从消息池中取出一个msg的方法: public static Message obtain(Handler h, int what, int arg1, int arg2, Object obj) { Message m = obtain(); m.target = h; m

Hanlder Looper MessageQueue Message

Handler:处理消息 Message:消息 MessageQueue:消息队列 Looper:MessageQueue的管理者 MessageQueue: 消息队列.以先进先出的原则存放多个Message.MessageQueue是通过Handler进行管理,通过Looper.Prepare()创建Looper的同时会自动创建MessageQueue对象.UI主线程默认会创建Looper,其他线程需要手动创建.通过Looper. Prepare()和Looper. Looper.loop()

Android面试---Handler,Looper,MessageQueue

首先说几个概念 1.MessageQueue:是一种 数据 结构,就是一个消息队列,存放消息的地方.每一个线程最多只可以拥有一个MessageQueue数据结构. 创建一个线程的时候,并不会自动 创建其MessageQueue.通常使用一个Looper对象对该线程的MessageQueue进行管理.主线程创建时,会创建一 个默认的Looper对象,而Looper对象的创建,将自动创建一个Message Queue.其他非主线程,不会自动创建Looper,要需要的时候,通过调 用prepare函数

Handler Looper MessageQueue源码解析

Handler依赖于Looper,它的创建需要该线程下的Looper已经存在,而该 Looper又会有与当前的线程进行绑定,所以该Handler所处线程就是Looper创建时所在的线程. Handler的dispatchMessage方法是在创建Handler时所用的Looper中执行的,这样就成功的将代码逻辑切换到指定的线程中去执行了. 所以,handler发送消息(send)可以在任意的线程中,但是接收消息一定是在创建Handler时所用的Looper中的线程里. Looper 先解释一下T