Android教程網
  1. 首頁
  2. Android 技術
  3. Android 手機
  4. Android 系統教程
  5. Android 游戲
 Android教程網 >> Android技術 >> 關於Android編程 >> 【Android】多線程

【Android】多線程

編輯:關於Android編程

進程概念
  一般可以在同一時間內執行多個程序的操作系統都有進程的概念。一個進程就是一個執行中的程序,而每一個進程都有自己獨立的一塊內存空間、一組系統資源。在進程的概念中,每一個進程的內部數據和狀態都是完全獨立的。
線程概念
  多線程指的是在單個程序中可以同時運行多個不同的線程,執行不同的任務。多線程意味著一個程序的多行語句可以看上去幾乎在同一時間內同時運行。
  線程與進程相似,是一段完成某個特定功能的代碼,是程序中單個順序的流控制。但與進程不同的是,同類的多個線程共享一塊內存空間和一組系統資源,所以系統在各個線程之間切換時,資源占用要比進程小得多,正因如此,線程也被稱為輕量級進程。一個進程中可以包含多個線程。圖所示是計時器程序進程和線程之間的關系,主線程負責管理子線程,即子線程的啟動、掛起、停止等操作。
  關於進程與線程的介紹在此不做過多敘述,不明白的參考計算機操作系統相關書籍。
  
Java中的線程
  Java的線程類為java.lang.Thread類。Java中每個線程都是通過某個特定Thread對象的方法run()來完成其操作的,方法run( )稱為線程體。注意線程的創建時間為Thread對象被創建的時候,所以主線程和子線程在時間線上是不同時的,根據代碼的順序執行原則,當運行到Thread創建的時候才會開一個新的線程。
構建線程類幾種常用的方法:

public Thread() public Thread(Runnable target) public Thread(Runnable target, String name)

public Thread(String name)

在Java中有兩種方法實現線程體:一是繼承線程類Thread,二是實現接口Runnable。由於繼承類只能繼承一個,所以一般我習慣使用實現接口Runnable的方式實現線程體。而在Android中,比較習慣采用構造一個匿名內部類的方式實現。

 new Thread(new Runnable() {
            @Override
            public void run() {
                //-------------------------接收內容數據------------------------------------
               /*你需要做的費時操作 數據處理等等*/
                handler.sendEmptyMessage(COMPLETE);
            }
        }).start();

在Android中,所有對UI的操作都應該放在UI線程即主線程中,而子線程去完成比較費時的編解碼、數據處理、數據庫查詢等等內容。雖然Android要求對界面屬性的更改要在主線程,但不是所有的界面刷新行為都需要放到Main線程處理,例如TextView的setText()方法需要在Main線程中, 否則會拋出CalledFromWrongThreadException,而ProgressBar的setProgress()方法則不需要在 Main線程中處理。
  那麼子線程運行完畢之後的結果如何返回體現在UI主線程之上,從而更新與用戶交互的動態內容,就涉及到了線程間的通信及消息傳遞問題。這裡我們首先看一下4個消息傳遞的類的內容。
  
  Handler在android裡負責發送和處理消息,通過它可以實現其他線程與Main線程之間的消息通訊。
  Looper負責管理線程的消息隊列和消息循環
  Message是線程間通訊的消息載體。兩個碼頭之間運輸貨物,Message充當集裝箱的功能,裡面可以存放任何你想要傳遞的消息。
  MessageQueue是消息隊列,先進先出,它的作用是保存有待線程處理的消息。
  
  它們四者之間的關系是,在其他線程中調用Handler.sendMsg()方法(參數是Message對象),將需要Main線程處理的事件 添加到Main線程的MessageQueue中,Main線程通過MainLooper從消息隊列中取出Handler發過來的這個消息時,會回調 Handler的handlerMessage()方法。
  Handler如果使用sendMessage的方式把消息入隊到消息隊列中,需要傳遞一個Message對象,而在Handler中,需要重 寫handleMessage()方法,用於獲取工作線程傳遞過來的消息,此方法運行在UI線程上。下面先介紹一下Message。

Message是一個final類,所以不可被繼承。Message封裝了線程中傳遞的消息,如果對於一般的數據,Message提供了getData()和setData()方法來獲取與設置數據,其中操作的數據是一個Bundle對 象,這個Bundle對象提供一系列的getXxx()和setXxx()方法用於傳遞基本數據類型的鍵值對,對於基本數據類型,使用起來很簡單,這裡不 再詳細講解。而對於復雜的數據類型,如一個對象的傳遞就要相對復雜一些。在Bundle中提供了兩個方法,專門用來傳遞對象的,但是這兩個方法也有相應的 限制,需要實現特定的接口,當然,一些Android自帶的類,其實已經實現了這兩個接口中的某一個,可以直接使用。方法如下:

putParcelable(String key,Parcelable value):需要傳遞的對象類實現Parcelable接口。
pubSerializable(String key,Serializable value):需要傳遞的對象類實現Serializable接口。

還有另外一種方式在Message中傳遞對象,那就是使用Message自帶的obj屬性傳值,它是一個Object類型,所以可以傳遞任意類型的對象,Message自帶的有如下幾個屬性:

int arg1:參數一,用於傳遞不復雜的數據,復雜數據使用setData()傳遞。
int arg2:參數二,用於傳遞不復雜的數據,復雜數據使用setData()傳遞。
Object obj:傳遞一個任意的對象。
int what:定義的消息碼,一般用於設定消息的標志。

對於Message對象,一般並不推薦直接使用它的構造方法得到,而是建議通過使用Message.obtain()這個靜態的方法或者 Handler.obtainMessage()獲取。Message.obtain()會從消息池中獲取一個Message對象,如果消息池中是空的, 才會使用構造方法實例化一個新Message,這樣有利於消息資源的利用。並不需要擔心消息池中的消息過多,它是有上限的,上限為10個。 Handler.obtainMessage()具有多個重載方法,如果查看源碼,會發現其實Handler.obtainMessage()在內部也是 調用的Message.obtain()。
  
  在thread的run方法中設置所發的Message內容,也可使用sendEmptyMessage等方法

// 獲取一個Message對象,設置what為1
Message msg = Message.obtain();
msg.obj = data;
msg.what = IS_FINISH;
// 發送這個消息到消息隊列中
handler.sendMessage(msg);

  Message.obtain()方法具有多個重載方法,大致可以分為為兩類,一類是無需傳遞Handler對象,對於這類的方法,當填充好消 息後,需要調用Handler.sendMessage()方法來發送消息到消息隊列中。第二類需要傳遞一個Handler對象,這類方法可以直接使用 Message.sendToTarget()方法發送消息到消息隊列中,這是因為在Message對象中有一個私有的Handler類型的屬性 Target,當時obtain方法傳遞進一個Handler對象的時候,會給Target屬性賦值,當調用sendToTarget()方法的時候,實 際在它內部還是調用的Target.sendMessage()方法。

  在Handler中,也定義了一些發送空消息的方法,如:sendEmptyMessage(int what)、sendEmptyMessageDelayed(int what,long delayMillis),看似這些方法沒有使用Message就可以發送一個消息,但是如果查看源碼就會發現,其實內部也是從 Message.obtain()方法中獲取一個Message對象,然後給屬性賦值,最後使用sendMessage()發送消息到消息隊列中。

  Handler中,與Message發送消息相關的方法有:

Message obtainMessage():獲取一個Message對象。
boolean sendMessage():發送一個Message對象到消息隊列中,並在UI線程取到消息後,立即執行。
boolean sendMessageDelayed():發送一個Message對象到消息隊列中,在UI線程取到消息後,延遲執行。
boolean sendEmptyMessage(int what):發送一個空的Message對象到隊列中,並在UI線程取到消息後,立即執行。
boolean sendEmptyMessageDelayed(int what,long delayMillis):發送一個空Message對象到消息隊列中,在UI線程取到消息後,延遲執行。
void removeMessage():從消息隊列中移除一個未響應的消息。

Handler 的接收端,根據不同的的message.what設置不同的響應即可

    private class ContentActivityHandler extends Handler{
        @Override
        public void handleMessage(Message msg) {
            switch (msg.what){
                case COMPLETE:set_Content();break;
                default:break;
            }
        }
    }
  1. 上一頁:
  2. 下一頁:
熱門文章
閱讀排行版
Copyright © Android教程網 All Rights Reserved