真实的国产乱ⅩXXX66竹夫人,五月香六月婷婷激情综合,亚洲日本VA一区二区三区,亚洲精品一区二区三区麻豆

成都創(chuàng)新互聯(lián)網(wǎng)站制作重慶分公司

Android消息隊(duì)列模型詳解及實(shí)例

Android 消息隊(duì)列模型詳解及實(shí)例

網(wǎng)站建設(shè)哪家好,找創(chuàng)新互聯(lián)!專注于網(wǎng)頁(yè)設(shè)計(jì)、網(wǎng)站建設(shè)、微信開發(fā)、重慶小程序開發(fā)公司、集團(tuán)企業(yè)網(wǎng)站建設(shè)等服務(wù)項(xiàng)目。為回饋新老客戶創(chuàng)新互聯(lián)還提供了高唐免費(fèi)建站歡迎大家使用!

Android系統(tǒng)的消息隊(duì)列和消息循環(huán)都是針對(duì)具體線程的,一個(gè)線程可以存在(當(dāng)然也可以不存在)一個(gè)消息隊(duì)列(Message Queue)和一個(gè)消息循環(huán)(Looper)。Android中除了UI線程(主線程),創(chuàng)建的工作線程默認(rèn)是沒有消息循環(huán)和消息隊(duì)列的。如果想讓該線程具有消息隊(duì)列和消息循環(huán),并具有消息處理機(jī)制,就需要在線程中首先調(diào)用Looper.prepare()來創(chuàng)建消息隊(duì)列,然后調(diào)用Looper.loop()進(jìn)入消息循環(huán)。如以下代碼所示:

class LooperThread extends Thread { 
  public Handler mHandler; 
 
  public void run() { 
   Looper.prepare(); 
 
   mHandler = new Handler() { 
    public void handleMessage(Message msg) { 
     // process incoming messages here 
    } 
   }; 
 
   Looper.loop(); 
  } 
 } 

      這樣該線程就具有了消息處理機(jī)制了。如果不調(diào)用Looper.prepare()來創(chuàng)建消息隊(duì)列,會(huì)報(bào)"Java.lang.RuntimeException: Can't create handler inside thread that has not called Looper.prepare()"的錯(cuò)誤。 

       通過下圖可以清晰顯示出UI Thread, Worker Thread, Handler, Massage Queue, Looper之間的關(guān)系:

 Android 消息隊(duì)列模型詳解及實(shí)例

       解釋上圖中的幾個(gè)基本概念: 

       1.Message

       消息對(duì)象,顧名思義就是記錄消息信息的類。這個(gè)類有幾個(gè)比較重要的字段:

       a.arg1和arg2:我們可以使用兩個(gè)字段用來存放我們需要傳遞的整型值,在Service中,我們可以用來存放Service的ID。
       b.obj:該字段是Object類型,我們可以讓該字段傳遞某個(gè)多項(xiàng)到消息的接受者中。
       c.what:這個(gè)字段可以說是消息的標(biāo)志,在消息處理中,我們可以根據(jù)這個(gè)字段的不同的值進(jìn)行不同的處理,類似于我們?cè)谔幚鞡utton事件時(shí),通過switch(v.getId())判斷是點(diǎn)擊了哪個(gè)按鈕。

       在使用Message時(shí),我們可以通過new Message()創(chuàng)建一個(gè)Message實(shí)例,但是Android更推薦我們通過Message.obtain()或者Handler.obtainMessage()獲取Message對(duì)象。這并不一定是直接創(chuàng)建一個(gè)新的實(shí)例,而是先從消息池中看有沒有可用的Message實(shí)例,存在則直接取出并返回這個(gè)實(shí)例。反之如果消息池中沒有可用的Message實(shí)例,則根據(jù)給定的參數(shù)new一個(gè)新Message對(duì)象。通過分析源碼可得知,Android系統(tǒng)默認(rèn)情況下在消息池中實(shí)例化10個(gè)Message對(duì)象。 

       2.MessageQueue

       消息隊(duì)列,用來存放Message對(duì)象的數(shù)據(jù)結(jié)構(gòu),按照“先進(jìn)先出”的原則存放消息。存放并非實(shí)際意義的保存,而是將Message對(duì)象以鏈表的方式串聯(lián)起來的。MessageQueue對(duì)象不需要我們自己創(chuàng)建,而是有Looper對(duì)象對(duì)其進(jìn)行管理,一個(gè)線程最多只可以擁有一個(gè)MessageQueue。我們可以通過Looper.myQueue()獲取當(dāng)前線程中的MessageQueue。 

       3.Looper

       MessageQueue的管理者,在一個(gè)線程中,如果存在Looper對(duì)象,則必定存在MessageQueue對(duì)象,并且只存在一個(gè)Looper對(duì)象和一個(gè)MessageQueue對(duì)象。倘若我們的線程中存在Looper對(duì)象,則我們可以通過Looper.myLooper()獲取,此外我們還可以通過Looper.getMainLooper()獲取當(dāng)前應(yīng)用系統(tǒng)中主線程的Looper對(duì)象。在這個(gè)地方有一點(diǎn)需要注意,假如Looper對(duì)象位于應(yīng)用程序主線程中,則Looper.myLooper()和Looper.getMainLooper()獲取的是同一個(gè)對(duì)象。 

       4.Handler

       消息的處理者。通過Handler對(duì)象我們可以封裝Message對(duì)象,然后通過sendMessage(msg)把Message對(duì)象添加到MessageQueue中;當(dāng)MessageQueue循環(huán)到該Message時(shí),就會(huì)調(diào)用該Message對(duì)象對(duì)應(yīng)的handler對(duì)象的handleMessage()方法對(duì)其進(jìn)行處理。由于是在handleMessage()方法中處理消息,因此我們應(yīng)該編寫一個(gè)類繼承自Handler,然后在handleMessage()處理我們需要的操作。 

       另外,我們知道,Android UI操作并不是線程安全的,所以無(wú)法在子線程中更新UI。但Andriod提供了幾種方法,可以在子線程中通知UI線程更新界面: 

  1. Activity.runOnUiThread( Runnable )
  2. View.post( Runnable )
  3. View.postDelayed( Runnable, long )
  4. Handler

       比較常用的是通過Handler,用Handler來接收子線程發(fā)送的數(shù)據(jù),并用此數(shù)據(jù)配合主線程更新UI。那么,只要在主線程中創(chuàng)建Handler對(duì)象,在子線程中調(diào)用Handler的sendMessage方法,就會(huì)把消息放入主線程的消息隊(duì)列,并且將會(huì)在Handler主線程中調(diào)用該handler的handleMessage方法來處理消息。  

package com.superonion; 
 
import android.app.Activity; 
import android.os.Bundle; 
import android.os.Message; 
import android.util.Log; 
import android.os.Handler; 
 
public class MyHandler extends Activity { 
  static final String TAG = "Handler"; 
  Handler h = new Handler(){ 
    public void handleMessage (Message msg) 
    { 
      switch(msg.what) 
      { 
      case HANDLER_TEST: 
        Log.d(TAG, "The handler thread id = " + Thread.currentThread().getId() + "\n"); 
        break; 
      } 
    } 
  }; 
 
  static final int HANDLER_TEST = 1; 
  /** Called when the activity is first created. */ 
  @Override 
  public void onCreate(Bundle savedInstanceState) { 
    super.onCreate(savedInstanceState); 
    Log.d(TAG, "The main thread id = " + Thread.currentThread().getId() + "\n"); 
 
    new myThread().start(); 
    setContentView(R.layout.main); 
  } 
 
  class myThread extends Thread 
  { 
    public void run() 
    { 
      Message msg = new Message(); 
      msg.what = HANDLER_TEST; 
      h.sendMessage(msg); 
      Log.d(TAG, "The worker thread id = " + Thread.currentThread().getId() + "\n"); 
    } 
  } 
} 
 

        以上代碼中,Handler在主線程中創(chuàng)建后,子線程通過sendMessage()方法就可以將消息發(fā)送到主線程中,并在handleMessage()方法中處理。

 感謝閱讀,希望能幫助大家,謝謝大家對(duì)本站的支持!


本文名稱:Android消息隊(duì)列模型詳解及實(shí)例
標(biāo)題路徑:http://weahome.cn/article/iepjod.html

其他資訊

在線咨詢

微信咨詢

電話咨詢

028-86922220(工作日)

18980820575(7×24)

提交需求

返回頂部