Android 中Message,MessageQueue,Looper,Handler详解

对于android初学者来说,这几个概念时常让人困惑,今天发现一篇文章感觉很不错,与君共享。

 

一、几个关键概念
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

  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

  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

  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 

  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

 

  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>  

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值