<rt id="bn8ez"></rt>
<label id="bn8ez"></label>

  • <span id="bn8ez"></span>

    <label id="bn8ez"><meter id="bn8ez"></meter></label>

    統計

    留言簿(1)

    DB

    Others

    QA

    Tech Website

    閱讀排行榜

    評論排行榜

    【轉】深入理解Android消息處理系統

         熟悉Windows編程的朋友可能知道Windows程序是消息驅動的,并且有全局的消息循環系統。而Android應用程序也是消息驅動的,按道理來說也應該提供消息循環機制。實際上谷歌參考了Windows的消息循環機制,也在Android系統中實現了消息循環機制。Android通過Looper、Handler來實現消息循環機制,Android消息循環是針對線程的(每個線程都可以有自己的消息隊列和消息循環)。本文深入介紹一下Android消息處理系統原理。

        Android系統中Looper負責管理線程的消息隊列和消息循環,具體實現請參考Looper的源碼。 可以通過Loop.myLooper()得到當前線程的Looper對象,通過Loop.getMainLooper()可以獲得當前進程的主線程的Looper對象。

        前面提到Android系統的消息隊列和消息循環都是針對具體線程的,一個線程可以存在(當然也可以不存在)一個消息隊列和一個消息循環(Looper),特定線程的消息只能分發給本線程,不能進行跨線程,跨進程通訊。但是創建的工作線程默認是沒有消息循環和消息隊列的,如果想讓該線程具有消息隊列和消息循環,需要在線程中首先調用Looper.prepare()來創建消息隊列,然后調用Looper.loop()進入消息循環。如下例所示:

      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();
          }
      }

    這樣你的線程就具有了消息處理機制了,在Handler中進行消息處理。

         Activity是一個UI線程,運行于主線程中,Android系統在啟動的時候會為Activity創建一個消息隊列和消息循環(Looper)。詳細實現請參考ActivityThread.java文件。

         Handler的作用是把消息加入特定的(Looper)消息隊列中,并分發和處理該消息隊列中的消息。構造Handler的時候可以指定一個Looper對象,如果不指定則利用當前線程的Looper創建。詳細實現請參考Looper的源碼。

         Activity、Looper、Handler的關系如下圖所示:

         一個Activity中可以創建多個工作線程或者其他的組件,如果這些線程或者組件把他們的消息放入Activity的主線程消息隊列,那么該消息就會在主線程中處理了。因為主線程一般負責界面的更新操作,并且Android系統中的weget不是線程安全的,所以這種方式可以很好的實現Android界面更新。在Android系統中這種方式有著廣泛的運用。

         那么另外一個線程怎樣把消息放入主線程的消息隊列呢?答案是通過Handle對象,只要Handler對象以主線程的Looper創建,那么調用Handler的sendMessage等接口,將會把消息放入隊列都將是放入主線程的消息隊列。并且將會在Handler主線程中調用該handler的handleMessage接口來處理消息。

         這里面涉及到線程同步問題,請先參考如下例子來理解Handler對象的線程模型:

    1、首先創建MyHandler工程。

    2、在MyHandler.java中加入如下的代碼:

    package com.simon;
    
    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");
        	}
        }
    }

    在這個例子中我們主要是打印,這種處理機制各個模塊的所處的線程情況。如下是我的機器運行結果:

    09-10 23:40:51.478: DEBUG/Handler(302): The main thread id = 1
    09-10 23:40:51.569: DEBUG/Handler(302): The worker thread id = 8
    09-10 23:40:52.128: DEBUG/Handler(302): The handler thread id = 1

    我們可以看出消息處理是在主線程中處理的,在消息處理函數中可以安全的調用主線程中的任何資源,包括刷新界面。工作線程和主線程運行在不同的線程中,所以必須要注意這兩個線程間的競爭關系。

         上例中,你可能注意到在工作線程中訪問了主線程handler對象,并在調用handler的對象向消息隊列加入了一個消息。這個過程中會不會出現消息隊列數據不一致問題呢?答案是handler對象不會出問題,因為handler對象管理的Looper對象是線程安全的,不管是加入消息到消息隊列和從隊列讀出消息都是有同步對象保護的,具體請參考Looper.java文件。上例中沒有修改handler對象,所以handler對象不可能會出現數據不一致的問題。

         通過上面的分析,我們可以得出如下結論:

    1、如果通過工作線程刷新界面,推薦使用handler對象來實現。

    2、注意工作線程和主線程之間的競爭關系。推薦handler對象在主線程中構造完成(并且啟動工作線程之后不要再修改之,否則會出現數據不一致),然后在工作線程中可以放心的調用發送消息SendMessage等接口。

    3、除了2所述的hanlder對象之外的任何主線程的成員變量如果在工作線程中調用,仔細考慮線程同步問題。如果有必要需要加入同步對象保護該變量。

    4、handler對象的handleMessage接口將會在主線程中調用。在這個函數可以放心的調用主線程中任何變量和函數,進而完成更新UI的任務。

    5、Android很多API也利用Handler這種線程特性,作為一種回調函數的變種,來通知調用者。這樣Android框架就可以在其線程中將消息發送到調用者的線程消息隊列之中,不用擔心線程同步的問題。

         深入理解Android消息處理機制對于應用程序開發非常重要,也可以讓你對線程同步有更加深刻的認識。以上是最近Simon學習Android消息處理機制的一點兒總結,如有錯誤之處請不吝指教。

    參考資料:

    http://www.wscxy.com/nuaa/article.asp?id=116

    http://www.android1.net/Topic.aspx?BoardID=11&TopicID=631&Page=1

    http://www.android1.net/Topic.aspx?BoardID=11&TopicID=632

    http://www.android1.net/Topic.aspx?BoardID=11&TopicID=625

    posted on 2011-07-29 11:53 XXXXXX 閱讀(259) 評論(0)  編輯  收藏 所屬分類: Android Dev

    主站蜘蛛池模板: 久久99国产亚洲高清观看首页| 亚洲日韩AV一区二区三区中文| 国产亚洲AV夜间福利香蕉149| 中文字幕精品亚洲无线码二区| 自拍偷自拍亚洲精品被多人伦好爽| 国产成A人亚洲精V品无码 | 男女猛烈无遮掩视频免费软件| 两个人的视频www免费| 国产a v无码专区亚洲av| 一级毛片大全免费播放下载| 亚洲区不卡顿区在线观看| 国产精品亚洲综合| 免费h黄肉动漫在线观看| 一本久久A久久免费精品不卡| 桃子视频在线观看高清免费完整| 免费在线观看毛片| www一区二区www免费| 久久91亚洲人成电影网站| 99久久免费精品视频| 国产精品亚洲自在线播放页码| 大地资源中文在线观看免费版 | 18禁无遮挡无码网站免费| 亚洲欧美日韩中文无线码 | 色久悠悠婷婷综合在线亚洲| 在线观看黄片免费入口不卡| 亚洲国产精品久久久久婷婷老年| 尤物视频在线免费观看| 久久久久无码专区亚洲av| 一级毛片aaaaaa免费看| 污污的视频在线免费观看| 国产偷窥女洗浴在线观看亚洲| 亚洲成A人片在线播放器| 婷婷综合缴情亚洲狠狠尤物| 日韩a级无码免费视频| 国产成人精品日本亚洲直接| 深夜国产福利99亚洲视频| 青青草无码免费一二三区| 亚洲AV永久无码精品一福利| 亚洲av中文无码| 最近中文字幕免费完整| 国产精品亚洲精品日韩动图|