分享

Android线程间通信的Message机制

 只要坚持就能成功 2010-11-26
Android线程间通信的Message机制

1.1.Message
代码在frameworks\base\core\java\android\Os\Message.java中。

Message.obtain函数:有多个obtain函数,主要功能一样,只是参数不一样。作用是从Message Pool中取出一个Message,如果Message Pool中已经没有Message可取则新建一个Message返回,同时用对应的参数给得到的Message对象赋值。

Message Pool:大小为10个;通过Message.mPool->(Message并且Message.next)-> (Message并且Message.next)-> (Message并且Message.next)...构造一个Message Pool。Message Pool的第一个元素直接new出来,然后把Message.mPool(static类的static变量)指向它。其他的元素都是使用完的 Message通过Message的recycle函数清理后放到Message Pool(通过Message Pool最后一个Message的next指向需要回收的Message的方式实现)。下图为Message Pool的结构:


1.2.MessageQueue
MessageQueue里面有一个收到的Message的对列:

MessageQueue.mMessages(static变量)->( Message并且Message.next)-> ( Message并且Message.next)->...,下图为接收消息的消息队列:

上层代码通过Handler的sendMessage等函数放入一个message到MessageQueue里面时最终会调用 MessageQueue的 enqueueMessage函数。enqueueMessage根据上面的接收的Message的队列的构造把接收到的Message放入队列中。

MessageQueue的removeMessages函数根据上面的接收的Message的队列的构造把接收到的Message从队列中删除,并且调用对应Message对象的recycle函数把不用的Message放入Message Pool中。

1.3.Looper
Looper对象的创建是通过prepare函数,而且每一个Looper对象会和一个线程关联

Java代码
  1.    1. public static final void prepare() {  
  2.    2.     if (sThreadLocal.get() != null) {  
  3.    3.         throw new RuntimeException("Only one Looper may be created per thread");  
  4.    4.     }  
  5.    5.     sThreadLocal.set(new Looper());  
  6.    6. }  
复制代码
  1. public static final void prepare() {
  2.     if (sThreadLocal.get() != null) {
  3.         throw new RuntimeException("Only one Looper may be created per thread");
  4.     }
  5.     sThreadLocal.set(new Looper());
  6. }
复制代码
Looper对象创建时会创建一个MessageQueue,主线程默认会创建一个Looper从而有MessageQueue,其他线程默认是没有 MessageQueue的不能接收Message,如果需要接收Message则需要通过prepare函数创建一个MessageQueue。具体操作请见示例代码。

Java代码
  1.    1. private Looper() {  
  2.    2.     mQueue = new MessageQueue();  
  3.    3.     mRun = true;  
  4.    4.     mThread = Thread.currentThread();  
  5.    5. }  
复制代码
private Looper() {
    mQueue = new MessageQueue();
    mRun = true;
    mThread = Thread.currentThread();
}



prepareMainLooper函数只给主线程调用(系统处理,程序员不用处理),它会调用prepare建立Looper对象和MessageQueue。

Java代码

   1. public static final void prepareMainLooper() {  
   2.     prepare();  
   3.     setMainLooper(myLooper());  
   4.     if (Process.supportsProcesses()) {  
   5.         myLooper().mQueue.mQuitAllowed = false;  
   6.     }  
   7. }  

public static final void prepareMainLooper() {
    prepare();
    setMainLooper(myLooper());
    if (Process.supportsProcesses()) {
        myLooper().mQueue.mQuitAllowed = false;
    }
}



Loop函数从MessageQueue中从前往后取出Message,然后通过Handler的dispatchMessage函数进行消息的处理(可见消息的处理是Handler负责的),消息处理完了以后通过Message对象的recycle函数放到Message Pool中,以便下次使用,通过Pool的处理提供了一定的内存管理从而加速消息对象的获取。至于需要定时处理的消息如何做到定时处理,请见 MessageQueue的next函数,它在取Message来进行处理时通过判断MessageQueue里面的Message是否符合时间要求来决定是否需要把Message取出来做处理,通过这种方式做到消息的定时处理。

Java代码
  1. 1. public static final void loop() {  
  2.    2.     Looper me = myLooper();  
  3.    3.     MessageQueue queue = me.mQueue;  
  4.    4.     while (true) {  
  5.    5.         Message msg = queue.next(); // might block  
  6.    6.         //if (!me.mRun) {  
  7.    7.         //    break;  
  8.    8.         //}  
  9.    9.         if (msg != null) {  
  10.   10.             if (msg.target == null) {  
  11.   11.                 // No target is a magic identifier for the quit message  
  12.   12.                 return;  
  13.   13.             }  
  14.   14.   
  15.   15.             if (me.mLogging!= null)   
  16.   16.                 me.mLogging.println(">>>>> Dispatching to " + msg.target + " "+ msg.callback + ": " + msg.what);  
  17.   17.             msg.target.dispatchMessage(msg);  
  18.   18.             if (me.mLogging!= null)   
  19.   19.                 me.mLogging.println("<<<<< Finished to" + msg.target + " "+ msg.callback);  
  20.   20.             msg.recycle();  
  21.   21.         }  
  22.   22.     }  
  23.   23. }  

  24. public static final void loop() {
  25.     Looper me = myLooper();
  26.     MessageQueue queue = me.mQueue;
  27.     while (true) {
  28.         Message msg = queue.next(); // might block
  29.         //if (!me.mRun) {
  30.         //    break;
  31.         //}
  32.         if (msg != null) {
  33.             if (msg.target == null) {
  34.                 // No target is a magic identifier for the quit message
  35.                 return;
  36.             }

  37.             if (me.mLogging!= null)
  38.                 me.mLogging.println(">>>>> Dispatching to " + msg.target + " "+ msg.callback + ": " + msg.what);
  39.             msg.target.dispatchMessage(msg);
  40.             if (me.mLogging!= null)
  41.                 me.mLogging.println("<<<<< Finished to" + msg.target + " "+ msg.callback);
  42.             msg.recycle();
  43.         }
  44.     }
  45. }
复制代码
1.4.Handler

Handler的构造函数表示Handler会有成员变量指向Looper和MessageQueue,后面我们会看到没什么需要这些引用;至于callback是实现了Callback接口的对象,后面会看到这个对象的作用。

Java代码

   1. public Handler(Looper looper, Callback callback) {  
   2.     mLooper = looper;  
   3.     mQueue = looper.mQueue;  
   4.     mCallback = callback;  
   5. }  
   6.   
   7. public interface Callback {  
   8.     public boolean handleMessage(Message msg);  
   9. }  

public Handler(Looper looper, Callback callback) {
    mLooper = looper;
    mQueue = looper.mQueue;
    mCallback = callback;
}

public interface Callback {
    public boolean handleMessage(Message msg);
}



获取消息:直接通过Message的obtain方法获取一个Message对象。

Java代码

   1. public final Message obtainMessage(int what, int arg1, int arg2, Object obj){  
   2.     return Message.obtain(this, what, arg1, arg2, obj);  
   3. }  

public final Message obtainMessage(int what, int arg1, int arg2, Object obj){
    return Message.obtain(this, what, arg1, arg2, obj);
}



发送消息:通过MessageQueue的enqueueMessage把Message对象放到MessageQueue的接收消息队列中

Java代码

   1. public boolean sendMessageAtTime(Message msg, long uptimeMillis){  
   2.     boolean sent = false;  
   3.     MessageQueue queue = mQueue;  
   4.     if (queue != null) {  
   5.         msg.target = this;  
   6.     sent = queue.enqueueMessage(msg, uptimeMillis);  
   7.     } else {  
   8.         RuntimeException e = new RuntimeException(this + " sendMessageAtTime() called with no mQueue");  
   9.         Log.w("Looper", e.getMessage(), e);  
  10.     }  
  11.     return sent;  
  12. }  

public boolean sendMessageAtTime(Message msg, long uptimeMillis){
    boolean sent = false;
    MessageQueue queue = mQueue;
    if (queue != null) {
        msg.target = this;
    sent = queue.enqueueMessage(msg, uptimeMillis);
    } else {
        RuntimeException e = new RuntimeException(this + " sendMessageAtTime() called with no mQueue");
        Log.w("Looper", e.getMessage(), e);
    }
    return sent;
}




线程如何处理MessageQueue中接收的消息:在Looper的loop函数中循环取出MessageQueue的接收消息队列中的消息,然后调用 Hander的dispatchMessage函数对消息进行处理,至于如何处理(相应消息)则由用户指定(三个方法,优先级从高到低:Message里面的Callback,一个实现了Runnable接口的对象,其中run函数做处理工作;Handler里面的mCallback指向的一个实现了 Callback接口的对象,里面的handleMessage进行处理;处理消息Handler对象对应的类继承并实现了其中 handleMessage函数,通过这个实现的handleMessage函数处理消息)。

Java代码

   1. public void dispatchMessage(Message msg) {  
   2.     if (msg.callback != null) {  
   3.         handleCallback(msg);  
   4.     } else {  
   5.         if (mCallback != null) {  
   6.             if (mCallback.handleMessage(msg)) {  
   7.                 return;  
   8.             }  
   9.         }  
  10.         handleMessage(msg);  
  11.     }  
  12. }  

public void dispatchMessage(Message msg) {
    if (msg.callback != null) {
        handleCallback(msg);
    } else {
        if (mCallback != null) {
            if (mCallback.handleMessage(msg)) {
                return;
            }
        }
        handleMessage(msg);
    }
}



Runnable说明:Runnable只是一个接口,实现了这个接口的类对应的对象也只是个普通的对象,并不是一个Java中的Thread。Thread类经常使用Runnable,很多人有误解,所以这里澄清一下。


从上可知以下关系图:

其中清理Message是Looper里面的loop函数指把处理过的Message放到Message的Pool里面去,如果里面已经超过最大值10个,则丢弃这个Message对象。

调用Handler是指Looper里面的loop函数从MessageQueue的接收消息队列里面取出消息,然后根据消息指向的Handler对象调用其对应的处理方法。
1.5.代码示例

下面我们会以android实例来展示对应的功能,程序界面于下:
g。
1

评分人数

  • zxhy2

程序代码如下,后面部分有代码说明:

Java代码
  1.    1. package com.android.messageexample;  
  2.    2. import android.app.Activity;  
  3.    3. import android.content.Context;  
  4.    4. import android.graphics.Color;  
  5.    5. import android.os.Bundle;  
  6.    6. import android.os.Handler;  
  7.    7. import android.os.Looper;  
  8.    8. import android.os.Message;  
  9.    9. import android.util.Log;  
  10.   10. import android.view.View;  
  11.   11. import android.view.View.OnClickListener;  
  12.   12. import android.widget.Button;  
  13.   13. import android.widget.LinearLayout;  
  14.   14. import android.widget.TextView;  
  15.   15. public class MessageExample extends Activity implements OnClickListener {  
  16.   16.  private final int WC = LinearLayout.LayoutParams.WRAP_CONTENT;  
  17.   17.     private final int FP = LinearLayout.LayoutParams.FILL_PARENT;  
  18.   18.     public TextView tv;  
  19.   19.     private EventHandler mHandler;  
  20.   20.     private Handler mOtherThreadHandler=null;  
  21.   21.     private Button btn, btn2, btn3, btn4, btn5, btn6;  
  22.   22.     private NoLooperThread noLooerThread = null;  
  23.   23.     private OwnLooperThread ownLooperThread = null;  
  24.   24.     private ReceiveMessageThread receiveMessageThread =null;  
  25.   25.     private Context context = null;  
  26.   26.     private final String sTag = "MessageExample";  
  27.   27.     private boolean postRunnable = false;  
  28.   28.   
  29.   29.  /** Called when the activity is first created. */  
  30.   30.  @Override  
  31.   31.     public void onCreate(Bundle savedInstanceState) {  
  32.   32.         super.onCreate(savedInstanceState);  
  33.   33.         context = this.getApplicationContext();  
  34.   34.         LinearLayout layout = new LinearLayout(this);  
  35.   35.         layout.setOrientation(LinearLayout.VERTICAL);  
  36.   36.         btn = new Button(this);  
  37.   37.         btn.setId(101);  
  38.   38.         btn.setText("message from main thread self");  
  39.   39.         btn.setOnClickListener(this);  
  40.   40.         LinearLayout.LayoutParams param =  
  41.   41.             new LinearLayout.LayoutParams(250,50);  
  42.   42.         param.topMargin = 10;  
  43.   43.         layout.addView(btn, param);  
  44.   44.         btn2 = new Button(this);  
  45.   45.         btn2.setId(102);  
  46.   46.         btn2.setText("message from other thread to main thread");  
  47.   47.         btn2.setOnClickListener(this);  
  48.   48.         layout.addView(btn2, param);  
  49.   49.         btn3 = new Button(this);  
  50.   50.         btn3.setId(103);  
  51.   51.         btn3.setText("message to other thread from itself");  
  52.   52.         btn3.setOnClickListener(this);  
  53.   53.         layout.addView(btn3, param);  
  54.   54.         btn4 = new Button(this);  
  55.   55.         btn4.setId(104);  
  56.   56.         btn4.setText("message with Runnable as callback from other thread to main thread");  
  57.   57.         btn4.setOnClickListener(this);  
  58.   58.         layout.addView(btn4, param);  
  59.   59.         btn5 = new Button(this);  
  60.   60.         btn5.setId(105);  
  61.   61.         btn5.setText("main thread's message to other thread");  
  62.   62.         btn5.setOnClickListener(this);  
  63.   63.         layout.addView(btn5, param);  
  64.   64.         btn6 = new Button(this);  
  65.   65.         btn6.setId(106);  
  66.   66.         btn6.setText("exit");  
  67.   67.         btn6.setOnClickListener(this);  
  68.   68.         layout.addView(btn6, param);  
  69.   69.         tv = new TextView(this);  
  70.   70.         tv.setTextColor(Color.WHITE);  
  71.   71.         tv.setText("");  
  72.   72.         LinearLayout.LayoutParams param2 =  
  73.   73.            new LinearLayout.LayoutParams(FP, WC);  
  74.   74.         param2.topMargin = 10;  
  75.   75.         layout.addView(tv, param2);  
  76.   76.         setContentView(layout);      
  77.   77.           
  78.   78.         //主线程要发送消息给other thread, 这里创建那个other thread  
  79.   79.   receiveMessageThread = new ReceiveMessageThread();  
  80.   80.   receiveMessageThread.start();  
  81.   81.     }  
  82.   82.   
  83.   83.  //implement the OnClickListener interface  
  84.   84.  @Override  
  85.   85.  public void onClick(View v) {  
  86.   86.   switch(v.getId()){  
  87.   87.   case 101:  
  88.   88.    //主线程发送消息给自己  
  89.   89.    Looper looper;  
  90.   90.    looper = Looper.myLooper();  //get the Main looper related with the main thread  
  91.   91.    //如果不给任何参数的话会用当前线程对应的Looper(这里就是Main Looper)为Handler里面的成员mLooper赋值  
  92.   92.    mHandler = new EventHandler(looper);   
  93.   93.    //mHandler = new EventHandler();  
  94.   94.    // 清除整个MessageQueue里的消息  
  95.   95.    mHandler.removeMessages(0);  
  96.   96.    String obj = "This main thread's message and received by itself!";  
  97.   97.    //得到Message对象  
  98.   98.    Message m = mHandler.obtainMessage(1, 1, 1, obj);  
  99.   99.    // 将Message对象送入到main thread的MessageQueue里面  
  100. 100.    mHandler.sendMessage(m);  
  101. 101.    break;  
  102. 102.   case 102:      
  103. 103.    //other线程发送消息给主线程  
  104. 104.    postRunnable = false;  
  105. 105.    noLooerThread = new NoLooperThread();  
  106. 106.    noLooerThread.start();  
  107. 107.    break;  
  108. 108.   case 103:   
  109. 109.    //other thread获取它自己发送的消息  
  110. 110.    tv.setText("please look at the error level log for other thread received message");  
  111. 111.    ownLooperThread = new OwnLooperThread();  
  112. 112.    ownLooperThread.start();  
  113. 113.    break;   
  114. 114.   case 104:      
  115. 115.    //other thread通过Post Runnable方式发送消息给主线程  
  116. 116.    postRunnable = true;  
  117. 117.    noLooerThread = new NoLooperThread();  
  118. 118.    noLooerThread.start();  
  119. 119.    break;  
  120. 120.   case 105:      
  121. 121.    //主线程发送消息给other thread  
  122. 122.    if(null!=mOtherThreadHandler){  
  123. 123.     tv.setText("please look at the error level log for other thread received message from main thread");  
  124. 124.     String msgObj = "message from mainThread";  
  125. 125.     Message mainThreadMsg = mOtherThreadHandler.obtainMessage(1, 1, 1, msgObj);  
  126. 126.     mOtherThreadHandler.sendMessage(mainThreadMsg);  
  127. 127.    }  
  128. 128.    break;  
  129. 129.   case 106:  
  130. 130.    finish();  
  131. 131.    break;  
  132. 132.   }  
  133. 133.  }  
  134. 134.  class EventHandler extends Handler  
  135. 135.  {  
  136. 136.   public EventHandler(Looper looper) {  
  137. 137.    super(looper);  
  138. 138.   }  
  139. 139.   public EventHandler() {  
  140. 140.    super();  
  141. 141.   }  
  142. 142.   public void handleMessage(Message msg) {  
  143. 143.    //可以根据msg.what执行不同的处理,这里没有这么做  
  144. 144.    switch(msg.what){  
  145. 145.    case 1:  
  146. 146.     tv.setText((String)msg.obj);  
  147. 147.     break;  
  148. 148.    case 2:  
  149. 149.     tv.setText((String)msg.obj);  
  150. 150.     noLooerThread.stop();  
  151. 151.     break;  
  152. 152.    case 3:  
  153. 153.     //不能在非主线程的线程里面更新UI,所以这里通过Log打印收到的消息  
  154. 154.     Log.e(sTag, (String)msg.obj);  
  155. 155.     ownLooperThread.stop();  
  156. 156.     break;  
  157. 157.    default:  
  158. 158.     //不能在非主线程的线程里面更新UI,所以这里通过Log打印收到的消息  
  159. 159.     Log.e(sTag, (String)msg.obj);  
  160. 160.     break;  
  161. 161.    }  
  162. 162.   }  
  163. 163.  }  
  164. 164.  //NoLooperThread  
  165. 165.  class NoLooperThread extends Thread{  
  166. 166.   private EventHandler mNoLooperThreadHandler;  
  167. 167.   public void run() {  
  168. 168.    Looper myLooper, mainLooper;  
  169. 169.    myLooper = Looper.myLooper();  
  170. 170.    mainLooper = Looper.getMainLooper();    //这是一个static函数  
  171. 171.    String obj;  
  172. 172.    if(myLooper == null){  
  173. 173.     mNoLooperThreadHandler = new EventHandler(mainLooper);  
  174. 174.     obj = "NoLooperThread has no looper and handleMessage function executed in main thread!";  
  175. 175.    }  
  176. 176.    else {  
  177. 177.     mNoLooperThreadHandler = new EventHandler(myLooper);  
  178. 178.     obj = "This is from NoLooperThread self and handleMessage function executed in NoLooperThread!";  
  179. 179.    }  
  180. 180.    mNoLooperThreadHandler.removeMessages(0);  
  181. 181.    if(false == postRunnable){  
  182. 182.     //send message to main thread  
  183. 183.     Message m = mNoLooperThreadHandler.obtainMessage(2, 1, 1, obj);  
  184. 184.     mNoLooperThreadHandler.sendMessage(m);  
  185. 185.     Log.e(sTag, "NoLooperThread id:" + this.getId());  
  186. 186.    }else{  
  187. 187.     //下面new出来的实现了Runnable接口的对象中run函数是在Main Thread中执行,不是在NoLooperThread中执行  
  188. 188.     //注意Runnable是一个接口,它里面的run函数被执行时不会再新建一个线程  
  189. 189.     //您可以在run上加断点然后在eclipse调试中看它在哪个线程中执行  
  190. 190.     mNoLooperThreadHandler.post(new Runnable(){   
  191. 191.      @Override   
  192. 192.      public void run() {   
  193. 193.       tv.setText("update UI through handler post runnalbe mechanism!");  
  194. 194.       noLooerThread.stop();  
  195. 195.      }   
  196. 196.     });   
  197. 197.    }  
  198. 198.   }  
  199. 199.  }  
  200. 200.   
  201. 201.  //OwnLooperThread has his own message queue by execute Looper.prepare();  
  202. 202.  class OwnLooperThread extends Thread{  
  203. 203.   private EventHandler mOwnLooperThreadHandler;  
  204. 204.   public void run() {  
  205. 205.    Looper.prepare();   
  206. 206.    Looper myLooper, mainLooper;  
  207. 207.    myLooper = Looper.myLooper();  
  208. 208.    mainLooper = Looper.getMainLooper();    //这是一个static函数  
  209. 209.    String obj;  
  210. 210.    if(myLooper == null){  
  211. 211.     mOwnLooperThreadHandler = new EventHandler(mainLooper);  
  212. 212.     obj = "OwnLooperThread has no looper and handleMessage function executed in main thread!";  
  213. 213.    }  
  214. 214.    else {  
  215. 215.     mOwnLooperThreadHandler = new EventHandler(myLooper);  
  216. 216.     obj = "This is from OwnLooperThread self and handleMessage function executed in NoLooperThread!";  
  217. 217.    }  
  218. 218.    mOwnLooperThreadHandler.removeMessages(0);  
  219. 219.    //给自己发送消息  
  220. 220.    Message m = mOwnLooperThreadHandler.obtainMessage(3, 1, 1, obj);  
  221. 221.    mOwnLooperThreadHandler.sendMessage(m);  
  222. 222.    Looper.loop();   
  223. 223.   }  
  224. 224.  }  
  225. 225.   
  226. 226.  //ReceiveMessageThread has his own message queue by execute Looper.prepare();  
  227. 227.  class ReceiveMessageThread extends Thread{  
  228. 228.   public void run() {  
  229. 229.    Looper.prepare();  
  230. 230.    mOtherThreadHandler = new Handler(){  
  231. 231.     public void handleMessage(Message msg) {  
  232. 232.      Log.e(sTag, (String)msg.obj);  
  233. 233.     }  
  234. 234.    };  
  235. 235.    Looper.loop();  
  236. 236.   }  
  237. 237.  }  
  238. 238.   
  239. 239. }  

  240. package com.android.messageexample;
  241. import android.app.Activity;
  242. import android.content.Context;
  243. import android.graphics.Color;
  244. import android.os.Bundle;
  245. import android.os.Handler;
  246. import android.os.Looper;
  247. import android.os.Message;
  248. import android.util.Log;
  249. import android.view.View;
  250. import android.view.View.OnClickListener;
  251. import android.widget.Button;
  252. import android.widget.LinearLayout;
  253. import android.widget.TextView;
  254. public class MessageExample extends Activity implements OnClickListener {
  255. private final int WC = LinearLayout.LayoutParams.WRAP_CONTENT;
  256.     private final int FP = LinearLayout.LayoutParams.FILL_PARENT;
  257.     public TextView tv;
  258.     private EventHandler mHandler;
  259.     private Handler mOtherThreadHandler=null;
  260.     private Button btn, btn2, btn3, btn4, btn5, btn6;
  261.     private NoLooperThread noLooerThread = null;
  262.     private OwnLooperThread ownLooperThread = null;
  263.     private ReceiveMessageThread receiveMessageThread =null;
  264.     private Context context = null;
  265.     private final String sTag = "MessageExample";
  266.     private boolean postRunnable = false;

  267. /** Called when the activity is first created. */
  268. @Override
  269.     public void onCreate(Bundle savedInstanceState) {
  270.         super.onCreate(savedInstanceState);
  271.         context = this.getApplicationContext();
  272.         LinearLayout layout = new LinearLayout(this);
  273.         layout.setOrientation(LinearLayout.VERTICAL);
  274.         btn = new Button(this);
  275.         btn.setId(101);
  276.         btn.setText("message from main thread self");
  277.         btn.setOnClickListener(this);
  278.         LinearLayout.LayoutParams param =
  279.             new LinearLayout.LayoutParams(250,50);
  280.         param.topMargin = 10;
  281.         layout.addView(btn, param);
  282.         btn2 = new Button(this);
  283.         btn2.setId(102);
  284.         btn2.setText("message from other thread to main thread");
  285.         btn2.setOnClickListener(this);
  286.         layout.addView(btn2, param);
  287.         btn3 = new Button(this);
  288.         btn3.setId(103);
  289.         btn3.setText("message to other thread from itself");
  290.         btn3.setOnClickListener(this);
  291.         layout.addView(btn3, param);
  292.         btn4 = new Button(this);
  293.         btn4.setId(104);
  294.         btn4.setText("message with Runnable as callback from other thread to main thread");
  295.         btn4.setOnClickListener(this);
  296.         layout.addView(btn4, param);
  297.         btn5 = new Button(this);
  298.         btn5.setId(105);
  299.         btn5.setText("main thread's message to other thread");
  300.         btn5.setOnClickListener(this);
  301.         layout.addView(btn5, param);
  302.         btn6 = new Button(this);
  303.         btn6.setId(106);
  304.         btn6.setText("exit");
  305.         btn6.setOnClickListener(this);
  306.         layout.addView(btn6, param);
  307.         tv = new TextView(this);
  308.         tv.setTextColor(Color.WHITE);
  309.         tv.setText("");
  310.         LinearLayout.LayoutParams param2 =
  311.            new LinearLayout.LayoutParams(FP, WC);
  312.         param2.topMargin = 10;
  313.         layout.addView(tv, param2);
  314.         setContentView(layout);     
  315.         
  316.         //主线程要发送消息给other thread, 这里创建那个other thread
  317.   receiveMessageThread = new ReceiveMessageThread();
  318.   receiveMessageThread.start();
  319.     }

  320. //implement the OnClickListener interface
  321. @Override
  322. public void onClick(View v) {
  323.   switch(v.getId()){
  324.   case 101:
  325.    //主线程发送消息给自己
  326.    Looper looper;
  327.    looper = Looper.myLooper();  //get the Main looper related with the main thread
  328.    //如果不给任何参数的话会用当前线程对应的Looper(这里就是Main Looper)为Handler里面的成员mLooper赋值
  329.    mHandler = new EventHandler(looper);
  330.    //mHandler = new EventHandler();
  331.    // 清除整个MessageQueue里的消息
  332.    mHandler.removeMessages(0);
  333.    String obj = "This main thread's message and received by itself!";
  334.    //得到Message对象
  335.    Message m = mHandler.obtainMessage(1, 1, 1, obj);
  336.    // 将Message对象送入到main thread的MessageQueue里面
  337.    mHandler.sendMessage(m);
  338.    break;
  339.   case 102:   
  340.    //other线程发送消息给主线程
  341.    postRunnable = false;
  342.    noLooerThread = new NoLooperThread();
  343.    noLooerThread.start();
  344.    break;
  345.   case 103:  
  346.    //other thread获取它自己发送的消息
  347.    tv.setText("please look at the error level log for other thread received message");
  348.    ownLooperThread = new OwnLooperThread();
  349.    ownLooperThread.start();
  350.    break;
  351.   case 104:     
  352.    //other thread通过Post Runnable方式发送消息给主线程
  353.    postRunnable = true;
  354.    noLooerThread = new NoLooperThread();
  355.    noLooerThread.start();
  356.    break;
  357.   case 105:     
  358.    //主线程发送消息给other thread
  359.    if(null!=mOtherThreadHandler){
  360.     tv.setText("please look at the error level log for other thread received message from main thread");
  361.     String msgObj = "message from mainThread";
  362.     Message mainThreadMsg = mOtherThreadHandler.obtainMessage(1, 1, 1, msgObj);
  363.     mOtherThreadHandler.sendMessage(mainThreadMsg);
  364.    }
  365.    break;
  366.   case 106:
  367.    finish();
  368.    break;
  369.   }
  370. }
  371. class EventHandler extends Handler
  372. {
  373.   public EventHandler(Looper looper) {
  374.    super(looper);
  375.   }
  376.   public EventHandler() {
  377.    super();
  378.   }
  379.   public void handleMessage(Message msg) {
  380.    //可以根据msg.what执行不同的处理,这里没有这么做
  381.    switch(msg.what){
  382.    case 1:
  383.     tv.setText((String)msg.obj);
  384.     break;
  385.    case 2:
  386.     tv.setText((String)msg.obj);
  387.     noLooerThread.stop();
  388.     break;
  389.    case 3:
  390.     //不能在非主线程的线程里面更新UI,所以这里通过Log打印收到的消息
  391.     Log.e(sTag, (String)msg.obj);
  392.     ownLooperThread.stop();
  393.     break;
  394.    default:
  395.     //不能在非主线程的线程里面更新UI,所以这里通过Log打印收到的消息
  396.     Log.e(sTag, (String)msg.obj);
  397.     break;
  398.    }
  399.   }
  400. }
  401. //NoLooperThread
  402. class NoLooperThread extends Thread{
  403.   private EventHandler mNoLooperThreadHandler;
  404.   public void run() {
  405.    Looper myLooper, mainLooper;
  406.    myLooper = Looper.myLooper();
  407.    mainLooper = Looper.getMainLooper();    //这是一个static函数
  408.    String obj;
  409.    if(myLooper == null){
  410.     mNoLooperThreadHandler = new EventHandler(mainLooper);
  411.     obj = "NoLooperThread has no looper and handleMessage function executed in main thread!";
  412.    }
  413.    else {
  414.     mNoLooperThreadHandler = new EventHandler(myLooper);
  415.     obj = "This is from NoLooperThread self and handleMessage function executed in NoLooperThread!";
  416.    }
  417.    mNoLooperThreadHandler.removeMessages(0);
  418.    if(false == postRunnable){
  419.     //send message to main thread
  420.     Message m = mNoLooperThreadHandler.obtainMessage(2, 1, 1, obj);
  421.     mNoLooperThreadHandler.sendMessage(m);
  422.     Log.e(sTag, "NoLooperThread id:" + this.getId());
  423.    }else{
  424.     //下面new出来的实现了Runnable接口的对象中run函数是在Main Thread中执行,不是在NoLooperThread中执行
  425.     //注意Runnable是一个接口,它里面的run函数被执行时不会再新建一个线程
  426.     //您可以在run上加断点然后在eclipse调试中看它在哪个线程中执行
  427.     mNoLooperThreadHandler.post(new Runnable(){  
  428.      @Override  
  429.      public void run() {  
  430.       tv.setText("update UI through handler post runnalbe mechanism!");
  431.       noLooerThread.stop();
  432.      }  
  433.     });  
  434.    }
  435.   }
  436. }

  437. //OwnLooperThread has his own message queue by execute Looper.prepare();
  438. class OwnLooperThread extends Thread{
  439.   private EventHandler mOwnLooperThreadHandler;
  440.   public void run() {
  441.    Looper.prepare();
  442.    Looper myLooper, mainLooper;
  443.    myLooper = Looper.myLooper();
  444.    mainLooper = Looper.getMainLooper();    //这是一个static函数
  445.    String obj;
  446.    if(myLooper == null){
  447.     mOwnLooperThreadHandler = new EventHandler(mainLooper);
  448.     obj = "OwnLooperThread has no looper and handleMessage function executed in main thread!";
  449.    }
  450.    else {
  451.     mOwnLooperThreadHandler = new EventHandler(myLooper);
  452.     obj = "This is from OwnLooperThread self and handleMessage function executed in NoLooperThread!";
  453.    }
  454.    mOwnLooperThreadHandler.removeMessages(0);
  455.    //给自己发送消息
  456.    Message m = mOwnLooperThreadHandler.obtainMessage(3, 1, 1, obj);
  457.    mOwnLooperThreadHandler.sendMessage(m);
  458.    Looper.loop();
  459.   }
  460. }

  461. //ReceiveMessageThread has his own message queue by execute Looper.prepare();
  462. class ReceiveMessageThread extends Thread{
  463.   public void run() {
  464.    Looper.prepare();
  465.    mOtherThreadHandler = new Handler(){
  466.     public void handleMessage(Message msg) {
  467.      Log.e(sTag, (String)msg.obj);
  468.     }
  469.    };
  470.    Looper.loop();
  471.   }
  472. }

  473. }
复制代码
说明(代码详细解释请见后文):

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

使用mHandler = new EevntHandler(Looper.myLooper()); 可建立用来处理当前线程的Handler对象;其中,EevntHandler是Handler的子类。

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

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

    0条评论

    发表

    请遵守用户 评论公约

    类似文章 更多