andriod提供了 Handler 跟 Looper 来满足线程间的通信

andriod提供了 Handler 和 Looper 来满足线程间的通信

Android----Thread+Handler 线程 消息循环( 转载)

近来找了一些关于android 线程间通信的资料,整理学习了一下,并制作了一个简单的例子。

 andriod 提供了 Handler Looper 来满足线程间的通信。例如一个子线程从网络上下载了一副图片,当它下载完成后会发送消息给主线程,这个消息是通过绑定在主线程的Handler 来传递的。

Android ,这里的线程分为有消息循环的线程和没有消息循环的线程,有消息循环的线程一般都会有一个Looper ,这个事android 的新 概念。我们的主线程(UI 线程)就是一个消息循环的线程。针对这种消息循环的机制,我们引入一个新的机制Handle ,我们有消息循环,就要往消息循环里 面发送相应的消息,自定义消息一般都会有自己对应的处理,消息的发送和清除,消息的的处理,把这些都封装在Handle 里面,注意Handle 只是针对那 些有Looper 的线程,不管是UI 线程还是子线程,只要你有Looper ,我就可以往你的消息队列里面添加东西,并做相应的处理。
但是这里还有一点,就是只要是关于UI 相关的东西,就不能放在子线程中,因为子线程是不能操作UI 的,只能进行数据、系统等其他非UI 的操作。
   在Android ,这里的线程分为有消息循环的线程和没有消息循环的线程,有消息循环的线程一般都会有一个Looper ,这个是android 的新概 念。我们的主线程(UI 线程)就是一个消息循环的线程。针对这种消息循环的机制,我们引入一个新的机制Handler ,我们有消息循环,就要往消息循环里 面发送相应的消息,自定义消息一般都会有自己对应的处理,消息的发送和清除,把这些都封装在Handler 里面,注意Handler 只是针对那 些有Looper 的线程,不管是UI 线程还是子线程,只要你有Looper ,我就可以往你的消息队列里面添加东西,并做相应的处理。

但是这里还有一点,就是只要是关于UI 相关的东西,就不能放在子线程中,因为子线程是不能操作UI 的,只能进行数据、系统等其他非UI 的操作。


  一个Handler 的创建它就会被绑定到这个线程的消息队列中,如果是在主线程创建的,那就不需要写代码来创建消息队列了,默认的消息队列会在主线程被创建。但是如果是在子线程的话,就必须在创建Handler 之前先初始化线程的消息队列。如下面的代码:

Java 代码

  1. class ChildThread extends Thread {  
  2.   
  3.     public void run() {  
  4.   
  5.         /* 
  6.          *  创建 handler 前先初始化Looper. 
  7.          */  
  8.         Looper.prepare();  
  9.   
  10.         /* 
  11.          *  在子线程创建handler ,所以会绑定到子线程的消息队列中 
  12.          * 
  13.          */  
  14.         mChildHandler = new Handler() {  
  15.   
  16.             public void handleMessage(Message msg) {  
  17.   
  18.                 /* 
  19.                  * Do some expensive operations there. 
  20.                  */  
  21.             }  
  22.         };  
  23.   
  24.         /* 
  25.          *  启动该线程的消息队列 
  26.          */  
  27.         Looper.loop();  
  28.     }  
  29. }  

class ChildThread extends Thread {

 

    public void run() {

 

        /*

         * 创建 handler 前先初始化Looper.

         */

        Looper.prepare();

 

        /*

         * 在子线程创建handler ,所以会绑定到子线程的消息队列中

         *

         */

        mChildHandler = new Handler() {

 

            public void handleMessage(Message msg) {

 

                /*

                 * Do some expensive operations there.

                  */

            }

        };

 

        /*

         * 启动该线程的消息队列

         */

        Looper.loop();

    }

}

 



Handler 收到消息后,就会运行handleMessage(…) 的回调函数,可以在里面做一些耗时的操作。




最后完成了操作要结束子线程时,记得调用quit() 来结束消息循环队列。

mChildHandler.getLooper().quit();



下面是一个线程间通信的小例子:

Java 代码

  1. /** 
  2.  *  
  3.  * @author allin.dev  
  4.  * http://allin.cnblogs.com 
  5.  *  
  6.  */  
  7. public class MainThread extends Activity {  
  8.   
  9.     private static final String TAG = "MainThread";  
  10.     private Handler mMainHandler, mChildHandler;  
  11.     private TextView info;  
  12.     private Button msgBtn;  
  13.   
  14.     @Override  
  15.     public void onCreate(Bundle savedInstanceState) {  
  16.         super.onCreate(savedInstanceState);  
  17.         setContentView(R.layout.main);  
  18.   
  19.         info = (TextView) findViewById(R.id.info);  
  20.         msgBtn = (Button) findViewById(R.id.msgBtn);  
  21.   
  22.         mMainHandler = new Handler() {  
  23.   
  24.             @Override  
  25.             public void handleMessage(Message msg) {  
  26.                 Log.i(TAG, "Got an incoming message from the child thread - "  
  27.                         + (String) msg.obj);  
  28.                 //  接收子线程的消息  
  29.                 info.setText((String) msg.obj);  
  30.             }  
  31.   
  32.         };  
  33.   
  34.         new ChildThread().start();  
  35.           
  36.           
  37.         msgBtn.setOnClickListener(new OnClickListener() {  
  38.   
  39.             @Override  
  40.             public void onClick(View v) {  
  41.                   
  42.                 if (mChildHandler != null) {  
  43.                       
  44.                     // 发送消息给子线程  
  45.                     Message childMsg = mChildHandler.obtainMessage();  
  46.                     childMsg.obj = mMainHandler.getLooper().getThread().getName() + " says Hello";  
  47.                     mChildHandler.sendMessage(childMsg);  
  48.                       
  49.                     Log.i(TAG, "Send a message to the child thread - " + (String)childMsg.obj);  
  50.   
  51.   
  52.                 }  
  53.             }  
  54.         });  
  55.   
  56.     }  
  57.   
  58.     public void onDestroy() {  
  59.       super.onDestroy();  
  60.         Log.i(TAG, "Stop looping the child thread's message queue");  
  61.   
  62.         mChildHandler.getLooper().quit();  
  63.     }  
  64.   
  65.     class ChildThread extends Thread {  
  66.   
  67.         private static final String CHILD_TAG = "ChildThread";  
  68.   
  69.         public void run() {  
  70.             this.setName("ChildThread");  
  71.   
  72.             // 初始化消息循环队列,需要在Handler 创建之前  
  73.             Looper.prepare();  
  74.   
  75.             mChildHandler = new Handler() {  
  76.                 @Override  
  77.                 public void handleMessage(Message msg) {  
  78.                      Log.i(CHILD_TAG, "Got an incoming message from the main thread - " + (String)msg.obj);  
  79.   
  80.   
  81.                     try {  
  82.   
  83.                         // 在子线程中可以做一些耗时的工作  
  84.                         sleep(100);  
  85.   
  86.                         Message toMain = mMainHandler.obtainMessage();  
  87.                         toMain.obj = "This is " + this.getLooper().getThread().getName() +  
  88.                                     ".  Did you send me \"" + (String)msg.obj + "\"?";  
  89.   
  90.                         mMainHandler.sendMessage(toMain);  
  91.   
  92.                         Log.i(CHILD_TAG, "Send a message to the main thread - " + (String)toMain.obj);  
  93.   
  94.                     } catch (InterruptedException e) {  
  95.                         // TODO Auto-generated catch block  
  96.                         e.printStackTrace();  
  97.                     }  
  98.                 }  
  99.   
  100.             };  
  101.   
  102.             Log.i(CHILD_TAG, "Child handler is bound to - "+ mChildHandler.getLooper().getThread().getName());  
  103.   
  104.             // 启动子线程消息循环队列  
  105.             Looper.loop();  
  106.         }  
  107.     }  
  108. }