一区二区三区日韩精品-日韩经典一区二区三区-五月激情综合丁香婷婷-欧美精品中文字幕专区

分享

Android線程間通信的Message機制

 只要堅持就能成功 2010-11-26
Android線程間通信的Message機制

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

Message.obtain函數(shù):有多個obtain函數(shù),主要功能一樣,只是參數(shù)不一樣。作用是從Message Pool中取出一個Message,如果Message Pool中已經(jīng)沒有Message可取則新建一個Message返回,同時用對應(yīng)的參數(shù)給得到的Message對象賦值。

Message Pool:大小為10個;通過Message.mPool->(Message并且Message.next)-> (Message并且Message.next)-> (Message并且Message.next)...構(gòu)造一個Message Pool。Message Pool的第一個元素直接new出來,然后把Message.mPool(static類的static變量)指向它。其他的元素都是使用完的 Message通過Message的recycle函數(shù)清理后放到Message Pool(通過Message Pool最后一個Message的next指向需要回收的Message的方式實現(xiàn))。下圖為Message Pool的結(jié)構(gòu):


1.2.MessageQueue
MessageQueue里面有一個收到的Message的對列:

MessageQueue.mMessages(static變量)->( Message并且Message.next)-> ( Message并且Message.next)->...,下圖為接收消息的消息隊列:

上層代碼通過Handler的sendMessage等函數(shù)放入一個message到MessageQueue里面時最終會調(diào)用 MessageQueue的 enqueueMessage函數(shù)。enqueueMessage根據(jù)上面的接收的Message的隊列的構(gòu)造把接收到的Message放入隊列中。

MessageQueue的removeMessages函數(shù)根據(jù)上面的接收的Message的隊列的構(gòu)造把接收到的Message從隊列中刪除,并且調(diào)用對應(yīng)Message對象的recycle函數(shù)把不用的Message放入Message Pool中。

1.3.Looper
Looper對象的創(chuàng)建是通過prepare函數(shù),而且每一個Looper對象會和一個線程關(guān)聯(lián)

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. }  
復(fù)制代碼
  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. }
復(fù)制代碼
Looper對象創(chuàng)建時會創(chuàng)建一個MessageQueue,主線程默認(rèn)會創(chuàng)建一個Looper從而有MessageQueue,其他線程默認(rèn)是沒有 MessageQueue的不能接收Message,如果需要接收Message則需要通過prepare函數(shù)創(chuàng)建一個MessageQueue。具體操作請見示例代碼。

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



prepareMainLooper函數(shù)只給主線程調(diào)用(系統(tǒng)處理,程序員不用處理),它會調(diào)用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函數(shù)從MessageQueue中從前往后取出Message,然后通過Handler的dispatchMessage函數(shù)進行消息的處理(可見消息的處理是Handler負(fù)責(zé)的),消息處理完了以后通過Message對象的recycle函數(shù)放到Message Pool中,以便下次使用,通過Pool的處理提供了一定的內(nèi)存管理從而加速消息對象的獲取。至于需要定時處理的消息如何做到定時處理,請見 MessageQueue的next函數(shù),它在取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. }
復(fù)制代碼
1.4.Handler

Handler的構(gòu)造函數(shù)表示Handler會有成員變量指向Looper和MessageQueue,后面我們會看到?jīng)]什么需要這些引用;至于callback是實現(xiàn)了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);
}



發(fā)送消息:通過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函數(shù)中循環(huán)取出MessageQueue的接收消息隊列中的消息,然后調(diào)用 Hander的dispatchMessage函數(shù)對消息進行處理,至于如何處理(相應(yīng)消息)則由用戶指定(三個方法,優(yōu)先級從高到低:Message里面的Callback,一個實現(xiàn)了Runnable接口的對象,其中run函數(shù)做處理工作;Handler里面的mCallback指向的一個實現(xiàn)了 Callback接口的對象,里面的handleMessage進行處理;處理消息Handler對象對應(yīng)的類繼承并實現(xiàn)了其中 handleMessage函數(shù),通過這個實現(xiàn)的handleMessage函數(shù)處理消息)。

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只是一個接口,實現(xiàn)了這個接口的類對應(yīng)的對象也只是個普通的對象,并不是一個Java中的Thread。Thread類經(jīng)常使用Runnable,很多人有誤解,所以這里澄清一下。


從上可知以下關(guān)系圖:

其中清理Message是Looper里面的loop函數(shù)指把處理過的Message放到Message的Pool里面去,如果里面已經(jīng)超過最大值10個,則丟棄這個Message對象。

調(diào)用Handler是指Looper里面的loop函數(shù)從MessageQueue的接收消息隊列里面取出消息,然后根據(jù)消息指向的Handler對象調(diào)用其對應(yīng)的處理方法。
1.5.代碼示例

下面我們會以android實例來展示對應(yīng)的功能,程序界面于下:
g。
1

評分人數(shù)

  • 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.         //主線程要發(fā)送消息給other thread, 這里創(chuàng)建那個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.    //主線程發(fā)送消息給自己  
  89.   89.    Looper looper;  
  90.   90.    looper = Looper.myLooper();  //get the Main looper related with the main thread  
  91.   91.    //如果不給任何參數(shù)的話會用當(dāng)前線程對應(yīng)的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線程發(fā)送消息給主線程  
  104. 104.    postRunnable = false;  
  105. 105.    noLooerThread = new NoLooperThread();  
  106. 106.    noLooerThread.start();  
  107. 107.    break;  
  108. 108.   case 103:   
  109. 109.    //other thread獲取它自己發(fā)送的消息  
  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方式發(fā)送消息給主線程  
  116. 116.    postRunnable = true;  
  117. 117.    noLooerThread = new NoLooperThread();  
  118. 118.    noLooerThread.start();  
  119. 119.    break;  
  120. 120.   case 105:      
  121. 121.    //主線程發(fā)送消息給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.    //可以根據(jù)msg.what執(zhí)行不同的處理,這里沒有這么做  
  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函數(shù)  
  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出來的實現(xiàn)了Runnable接口的對象中run函數(shù)是在Main Thread中執(zhí)行,不是在NoLooperThread中執(zhí)行  
  188. 188.     //注意Runnable是一個接口,它里面的run函數(shù)被執(zhí)行時不會再新建一個線程  
  189. 189.     //您可以在run上加斷點然后在eclipse調(diào)試中看它在哪個線程中執(zhí)行  
  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函數(shù)  
  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.    //給自己發(fā)送消息  
  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.         //主線程要發(fā)送消息給other thread, 這里創(chuàng)建那個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.    //主線程發(fā)送消息給自己
  326.    Looper looper;
  327.    looper = Looper.myLooper();  //get the Main looper related with the main thread
  328.    //如果不給任何參數(shù)的話會用當(dāng)前線程對應(yīng)的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線程發(fā)送消息給主線程
  341.    postRunnable = false;
  342.    noLooerThread = new NoLooperThread();
  343.    noLooerThread.start();
  344.    break;
  345.   case 103:  
  346.    //other thread獲取它自己發(fā)送的消息
  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方式發(fā)送消息給主線程
  353.    postRunnable = true;
  354.    noLooerThread = new NoLooperThread();
  355.    noLooerThread.start();
  356.    break;
  357.   case 105:     
  358.    //主線程發(fā)送消息給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.    //可以根據(jù)msg.what執(zhí)行不同的處理,這里沒有這么做
  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函數(shù)
  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出來的實現(xiàn)了Runnable接口的對象中run函數(shù)是在Main Thread中執(zhí)行,不是在NoLooperThread中執(zhí)行
  425.     //注意Runnable是一個接口,它里面的run函數(shù)被執(zhí)行時不會再新建一個線程
  426.     //您可以在run上加斷點然后在eclipse調(diào)試中看它在哪個線程中執(zhí)行
  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函數(shù)
  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.    //給自己發(fā)送消息
  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. }
復(fù)制代碼
說明(代碼詳細解釋請見后文):

使用Looper.myLooper靜態(tài)方法可以取得當(dāng)前線程的Looper對象。

使用mHandler = new EevntHandler(Looper.myLooper()); 可建立用來處理當(dāng)前線程的Handler對象;其中,EevntHandler是Handler的子類。

使用mHandler = new EevntHandler(Looper.getMainLooper()); 可建立用來處理main線程的Handler對象;其中,EevntHandler是Handler的子類。

    本站是提供個人知識管理的網(wǎng)絡(luò)存儲空間,所有內(nèi)容均由用戶發(fā)布,不代表本站觀點。請注意甄別內(nèi)容中的聯(lián)系方式、誘導(dǎo)購買等信息,謹(jǐn)防詐騙。如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請點擊一鍵舉報。
    轉(zhuǎn)藏 分享 獻花(0

    0條評論

    發(fā)表

    請遵守用戶 評論公約

    類似文章 更多

    亚洲高清欧美中文字幕| 国产午夜福利在线观看精品| 久久99国产精品果冻传媒| 日本高清不卡一二三区| 中文字幕乱码免费人妻av| 91福利免费一区二区三区| 国产日韩综合一区在线观看| 亚洲中文在线中文字幕91| 国内尹人香蕉综合在线| 国产高清精品福利私拍| 欧美一区二区三区十区| 日韩国产亚洲一区二区三区| 深夜视频成人在线观看| 国产三级视频不卡在线观看| 99福利一区二区视频| 亚洲精品熟女国产多毛| 国产精品欧美一区二区三区不卡 | 人妻少妇系列中文字幕| 精品日韩视频在线观看| 久一视频这里只有精品| 欧美日韩一区二区午夜| 亚洲国产精品国自产拍社区| 好吊日视频这里都是精品| 国产免费自拍黄片免费看| 免费性欧美重口味黄色| 69精品一区二区蜜桃视频| 中字幕一区二区三区久久蜜桃 | 日韩一区二区三区免费av| 国产激情国产精品久久源| 91一区国产中文字幕| 国产一区二区三中文字幕| 国产午夜精品福利免费不| 日韩不卡一区二区视频| 久久一区内射污污内射亚洲| 日本99精品在线观看| 亚洲中文字幕亲近伦片| 91欧美日韩中在线视频| 福利视频一区二区三区| 天海翼高清二区三区在线| 欧美野外在线刺激在线观看| 久草精品视频精品视频精品|