分享

android消息地址

 My镜像站 2012-01-17

  消息机制虽然常用到,但这次写的程序接触到了Looper,觉得这篇文章不错就转载了下来,工作不忙但也不轻松,何时写个原创呢?

一、    角色描述

1.Looper: 一个线程可以产生一个 Looper 对象,由它来管理此线程里的 Message Queue( 消息队列 )

2.Handler: 你可以构造 Handler 对象来与 Looper 沟通,以便 push 新消息到 Message Queue 里;或者接收 Looper( Message Queue 取出 ) 所送来的消息。

3. Message Queue( 消息队列 ): 用来存放线程放入的消息。

4 .线程: UI thread 通常就是 main thread ,而 Android 启动程序时会替它建立一个 Message Queue

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

 

在你的 Android 程序里,新诞生一个线程,或执行 (Thread) 时,并不会自动建立其 Message Loop

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

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

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

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

使用 mHandler = new EevntHandler(Looper.myLooper()); 可用来构造当前线程的 Handler 对象;其中, EevntHandler 是自已实现的 Handler 的子类别。

使用 mHandler = new EevntHandler(Looper.getMainLooper()); 可诞生用来处理 main 线程的 Handler 对象;其中, EevntHandler 是自已实现的 Handler 的子类别。

 

这样描述可能太抽像,下面举几个实际的例子来说明:

二、    举例

1. 同线程内不同组件间的消息传递

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

 

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

同线程不同组件之间的消息传递:

public class Activity1 extends Activity implements OnClickListener{

      Button button = null ;

      TextView text = null ;

      @Override

      protected void onCreate(Bundle savedInstanceState) {

             super .onCreate(savedInstanceState);

             setContentView(R.layout. activity1 );       

             button = (Button)findViewById(R.id. btn );

             button .setOnClickListener( this );

             text = (TextView)findViewById(R.id. content );

      }

      public void onClick(View v) {

             switch (v.getId()) {

             case R.id. btn :

                    Looper looper = Looper.myLooper (); // 取得当前线程里的 looper

                    MyHandler mHandler = new MyHandler(looper); // 构造一个 handler 使之可与 looper 通信

                    //buton 等组件可以由 mHandler 将消息传给 looper , 再放入 messageQueue , 同时 mHandler 也可以接受来自 looper 消息

                    mHandler.removeMessages(0);

                    String msgStr = " 主线程不同组件通信 : 消息来自 button" ;

                    Message m = mHandler.obtainMessage(1, 1, 1, msgStr); // 构造要传递的消息

                    mHandler.sendMessage(m); // 发送消息 : 系统会自动调用 handleMessage 方法来处理消息

                    break ;

 

             }           

      }    

      private class MyHandler extends Handler{            

             public MyHandler(Looper looper){

                    super (looper);

             }

             @Override

             public void handleMessage(Message msg) { // 处理消息

                    text .setText(msg. obj .toString());

             }           

      }

}

 

说明:

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

   looper = Looper.myLooper ();

调用 Looper 类别的静态 myLooper() 函数,以取得目前线程里的 Looper 对象 .

mHandler = new MyHandler (looper);

构造一个 MyHandler 对象来与 Looper 沟通。 Activity 等对象可以藉由 MyHandler 对象来将消息传给 Looper ,然后放入 MessageQueue 里; MyHandler 对象也扮演 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!" 于画面上,

 

角色综述(回顾) :

  (1)UI thread 通常就是 main thread ,而 Android 启动程序时会替它建立一个 MessageQueue

(2) 当然需要一个 Looper 对象,来管理该 MessageQueue

(3) 我们可以构造 Handler 对象来 push 新消息到 Message Queue 里;或者接收 Looper( Message Queue 取出 ) 所送来的消息。

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

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

 

子线程传递消息给主线程

public class Activity2 extends Activity implements OnClickListener{

      Button button = null ;

      TextView text = null ;

      MyHandler mHandler = null ;

      Thread thread ;

      @Override

      protected void onCreate(Bundle savedInstanceState) {

             super .onCreate(savedInstanceState);

             setContentView(R.layout. activity1 );       

             button = (Button)findViewById(R.id. btn );

             button .setOnClickListener( this );

             text = (TextView)findViewById(R.id. content );

      }

      public void onClick(View v) {

             switch (v.getId()) {

             case R.id. btn :

                    thread = new MyThread();

                    thread .start();

                    break ;

             }           

      }    

      private class MyHandler extends Handler{            

             public MyHandler(Looper looper){

                    super (looper);

             }

             @Override

             public void handleMessage(Message msg) { // 处理消息

                    text .setText(msg. obj .toString());

             }           

      }

      private class MyThread extends Thread{

             @Override

             public void run() {

                    Looper curLooper = Looper.myLooper ();

                    Looper mainLooper = Looper.getMainLooper ();

                    String msg ;

                    if (curLooper== null ){

                           mHandler = new MyHandler(mainLooper);

                           msg = "curLooper is null" ;

                    } else {

                           mHandler = new MyHandler(curLooper);

                           msg = "This is curLooper" ;

                    }

                    mHandler .removeMessages(0);

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

                    mHandler .sendMessage(m);

             }           

      }

}

说明:

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

mHandler = new MyHandler (mainLooper);

mHandler 属于主线程。

  mHandler.sendMessage(m);

就将 m 消息存入到主线程的 Message Queue 里。 mainLooper 看到 Message Queue 里有讯息,就会作出处理,于是由主线程执行到 mHandler handleMessage() 来处理消息。

下一节将会写一个关于应多线程请求网络数据的例子。

    本站是提供个人知识管理的网络存储空间,所有内容均由用户发布,不代表本站观点。请注意甄别内容中的联系方式、诱导购买等信息,谨防诈骗。如发现有害或侵权内容,请点击一键举报。
    转藏 分享 献花(0

    0条评论

    发表

    请遵守用户 评论公约

    类似文章 更多