活用Android的Message Queue(1)

系统 1623 0

1.  Message Queue 的角色

l     在你的 Android 程序里,新创建一个线程,或称线程 (Thread) 时,并不会自动建立其 Message Loop

l     Android 里并没有 Global Message Queue 数据结构,例如,不同 APK 里的对象不能透过 Massage Queue 来交换消息 (Message)

l     一个线程可以创建一个 Looper 对象,由它来管理此线程里的 Message Queue

l     你可以创建 Handler 对象来与 Looper 沟通,以便 push 新消息到 Message Queue 里或者接收 Looper( Message Queue 取出 ) 所送来的消息。

l     线程 A Handler 对象引用可以传递给别的线程,让别的线程 B C 等能发送消息来给线程 A( 存于 A Message Queue )

l     线程 A Message Queue 里的消息,只有线程 A 所属的对象可以处理之。

l     使用 Looper.myLooper 可以取得目前线程的 Looper 对象引用。

l     使用 mHandler =  new  EventHandler(Looper. myLooper ()) ; 可创建用来处理目前线程的 Handler 对象;其中, EventHandler Handler 的子类别。

l     使用 mHandler =  new  EventHandler(Looper. getMainLooper() ) ; 可创建用来处理 main 线程的 Handler 对象;其中, EventHandler Handler 的子类别。

 

2.  范例之一: Looper 类之角色

Looper 类别用来管理特定线程内对象之间的消息交换 (Message Exchange) 。你的应用程序可以创建许多个线程,或称线程 (Thread) 。而一个线程可以实例化许多个对象,这些对象之间常常需要互相交换消息。如果有这种需要,您可以替线程创建一个 Looper 类对象,来处理信息交换的管理工作。 Looper 对象会建立一个 MessageQueue 数据结构来存放各对象传来的消息 ( 包括 UI 事件或 System 事件等 ) 。如下图:

 

 

   每一个线程 (Thread ,或称「线程」 ) 里可含有一个 Looper 对象以及一个 MessageQueue 数据结构 。在你的应用程序里,可以 定义 Handler 的子类别来接收 Looper 所送出的消息

 

//----- Looper_01 范例  -----

package  com.misoo.kx04;

import  android.app.Activity;

import  android.graphics.Color;

import  android.os.Bundle;

import  android.os.Handler;

import  android.os.Looper;

import  android.os.Message;

import  android.view.View;

import  android.view.View.OnClickListener;

import  android.widget.Button;

import  android.widget.LinearLayout;

import  android.widget.TextView;

 

public   class  ac01  extends  Activity  implements  OnClickListener {

     private   final   int   WC  = LinearLayout.LayoutParams. WRAP_CONTENT ;

     private   final   int   FP  = LinearLayout.LayoutParams. FILL_PARENT ;

     public  TextView  tv ;

     private  EventHandler  mHandler ;

     private  Button  btn btn2 btn3 ;

   

     public   void  onCreate(Bundle icicle) {

         super .onCreate(icicle);

        LinearLayout layout =  new  LinearLayout( this );

        layout.setOrientation(LinearLayout. VERTICAL );

                              

         btn  =  new  Button( this );

         btn .setId(101);

         btn .setBackgroundResource(R.drawable. heart );

         btn .setText( "test looper" );

         btn .setOnClickListener( this );

        LinearLayout.LayoutParams param = new  LinearLayout.LayoutParams(100,50);

        param. topMargin  = 10;

        layout.addView( btn , param);

               

         btn2  =  new  Button( this );

         btn2 .setId(102);

         btn2 .setBackgroundResource(R.drawable. ok_blue );

         btn2 .setText( "exit" );

         btn2 .setOnClickListener( this );

        layout.addView( btn2 , param);

               

         tv  =  new  TextView( this );

         tv .setTextColor(Color. WHITE );

         tv .setText( "" );

        LinearLayout.LayoutParams param2 = new  LinearLayout.LayoutParams( FP WC );

        param2. topMargin  = 10;

        layout.addView( tv , param2);

        setContentView(layout);     

    }

         public   void  onClick(View v) {

            switch (v.getId()){

               case  101: Looper looper;

                    looper = Looper. myLooper ();

                    mHandler  =  new  EventHandler(looper);

                    mHandler .removeMessages(0);

                     //  清除整个 MessageQueue 里的事件,确保不会通知到别人

                    String obj =  "This my message!" ;

                    Message m =  mHandler .obtainMessage(1, 1, 1, obj);

                     //  组装成一个 Message 物件

                     mHandler .sendMessage(m);

                     //  Message 物件送入 MessageQueue

                       break ;

                case  102:

                  finish();

                   break ;

          }

   }

//------------------------------------------------------             

class  EventHandler  extends  Handler{

     public  EventHandler(Looper looper) {

        super (looper);

    }

     @Override

     public   void  handleMessage(Message msg) {

         tv .setText((String)msg. obj );

    }

  }

}

//-------------------------------------------------------

说明:

   程序启动时,当前线程 ( 即主线程 , main thread) 已创建了一个 Looper 对象,并且有了一个 MessageQueue 数据结构。

   指令: looper = Looper. myLooper (); 调用 Looper 类的静态 myLooper() 函数,以取得目前线程里的 Looper 对象引用。

指令: mHandler  =  new  EventHandler(looper); 创建 一个 EventHandler 对象来与 Looper 沟通。 Activity 等对象可以通过 EventHandler 对象来将消息传给 Looper ,然后放入 MessageQueue 里; EventHandler 对象也扮演 Listener 的角色,可接收 Looper 对象所送来的消息。如下图:

 

 

指令: Message m =  mHandler .obtainMessage(1, 1, 1, obj);   先创建一个 Message 对象,并将数据存入次对象里。

指令: mHandler .sendMessage(m);   通过 mHandler 对象而将消息 m 传给 Looper ,然后放入 MessageQueue 里。

此时 Looper 对象看到 MessageQueue 里有消息 m 就将它广播出去 mHandler 对象接到此消息时,会调用其 handleMessage() 函数来处理之,于是输出 "This my message!" 于画面上,如下:

 

 

 

3.  范例之二:由别的线程发送到主线程的 Message Queue

 

//----- Looper_02 范例  -----

package  com.misoo.kx04;

import  android.app.Activity;

import  android.graphics.Color;

import  android.os.Bundle;

import  android.os.Handler;

import  android.os.Looper;

import  android.os.Message;

import  android.view.View;

import  android.view.View.OnClickListener;

import  android.widget.Button;

import  android.widget.LinearLayout;

import  android.widget.TextView;

 

public   class  ac01  extends  Activity  implements  OnClickListener {

            private   final   int   WC  = LinearLayout.LayoutParams. WRAP_CONTENT ;

            private   final   int   FP  = LinearLayout.LayoutParams. FILL_PARENT ;

            public  TextView  tv ;

     private  myThread  t ;

     private  Button  btn btn2 btn3 ;

   

     public   void  onCreate(Bundle icicle) {

                 //文章长度有限,代码请参考上例

               }

               public   void  onClick(View v) {

                      switch (v.getId()){

                      case  101:

                        t  =  new  myThread();

                        t .start();

                        break ;

                      case  102:

                              finish();

                        break ;

                     }

           }

//------------------------------------------------------             

class  EHandler  extends  Handler {                                     //文章长度有限,代码请参考上例

   //------------------------------------------------------             

class  myThread  extends  Thread{

             private  EHandler  mHandler ;

public   void  run() {

                Looper myLooper, mainLooper;

                myLooper = Looper. myLooper ();

                mainLooper = Looper. getMainLooper ();

                String obj;

                 if (myLooper ==  null ){

                        mHandler  =  new  EHandler(mainLooper);

                       obj =  "current thread has no looper!" ;

                }

                 else  {

                      mHandler  =  new  EHandler(myLooper);

                     obj =  "This is from current thread." ;

                }

                 mHandler .removeMessages(0);

                Message m =  mHandler .obtainMessage(1, 1, 1, obj);

                 mHandler .sendMessage(m);

             }

  }

}

 

 

Android 会自动替主线程建立 Message Queue 在这个 子线程里并没有建立 Message Queue 。所以, myLooper 值为 null ,而 mainLooper 则指向主线程里的 Looper 对象。于是,执行到指令:

mHandler =  new  EHandler(mainLooper);  mHandler 属于主线程

指令: mHandler .sendMessage(m);

就将消息 m 存入到主线程的 Message Queue 里。 mainLooper 看到 Message Queue 里有消息,就会处理之,于是由主线程执行到 mHandler handleMessage() 函数来处理消息。此程序输出画面为:

活用Android的Message Queue(1)


更多文章、技术交流、商务合作、联系博主

微信扫码或搜索:z360901061

微信扫一扫加我为好友

QQ号联系: 360901061

您的支持是博主写作最大的动力,如果您喜欢我的文章,感觉我的文章对您有帮助,请用微信扫描下面二维码支持博主2元、5元、10元、20元等您想捐的金额吧,狠狠点击下面给点支持吧,站长非常感激您!手机微信长按不能支付解决办法:请将微信支付二维码保存到相册,切换到微信,然后点击微信右上角扫一扫功能,选择支付二维码完成支付。

【本文对您有帮助就好】

您的支持是博主写作最大的动力,如果您喜欢我的文章,感觉我的文章对您有帮助,请用微信扫描上面二维码支持博主2元、5元、10元、自定义金额等您想捐的金额吧,站长会非常 感谢您的哦!!!

发表我的评论
最新评论 总共0条评论