歡迎來到Linux教程網
Linux教程網
Linux教程網
Linux教程網
您现在的位置: Linux教程網 >> UnixLinux >  >> Linux編程 >> Linux編程

Android Handler Message多線程實例

什麼是Handler 

handler通俗講就是在各個進程之間發送數據的處理對象。在任何進程中,只要獲得了另一個進程的handler則可以通過 handler.sendMessage(message)方法向那個進程發送數據。基於這個機制,我們在處理多線程的時候可以新建一個thread,這 個thread擁有UI線程中的一個handler。當thread處理完一些耗時的操作後通過傳遞過來的handler向UI線程發送數據,由UI線程去更新界面。

Handler類簡介

在Android平台中,新啟動的線程是無法訪問Activity裡的Widget的,當然也不能將運行狀態外送出來,這就需要有Handler機 制進行消息的傳遞了,Handler類位於android.os包下,主要的功能是完成Activity的Widget與應用程序中線程之間的交互。接下 來對該類中常用的方法進行介紹,如下表所示。

 Handler類的常用方法

方法簽名

描     述

public void handleMessage (Message msg)

子類對象通過該方法接收信息

public final boolean sendEmptyMessage (int what)

發送一個只含有 what 值的消息

public final boolean sendMessage (Message msg)

發送消息到 Handler ,

通過 handleMessage 方法接收

public final boolean hasMessages (int what)

監測消息隊列中是否還

有 what 值的消息

public final boolean post (Runnable r)

將一個線程添加到消息隊列

 

開發帶有Handler類的程序步驟如下。

在Activity或Activity的Widget中開發Handler類的對象,並重寫handleMessage方法。

在新啟動的線程中調用sendEmptyMessage或者sendMessage方法向Handler發送消息。

Handler類的對象用handleMessage方法接收消息,然後根據消息的不同執行不同的操作。

    在Android 中Handler和Message、Thread有著很密切的關系。Handler 主要是負責Message的分發和處理。但是這個Message從哪裡來的呢?Message 由一個消息隊列進行管理,而消息隊列卻由一個Looper進行管理。Android系統中Looper負責管理線程的消息隊列和消息循環,具體實現請參考Looper的源碼。 可以通過Loop.myLooper()得到當前線程的Looper對象,通過Loop.getMainLooper()可以獲得當前進程的主線程的 Looper對象。Android系統的消息隊列和消息循環都是針對具體線程的,一個線程可以存在(當然也可以不存在)一個消息隊列和一個消 息循環(Looper),特定線程的消息只能分發給本線程,不能進行跨線程,跨進程通訊。但是創建的工作線程默認是沒有消息循環和消息隊列的,如果想讓該 線程具有消息隊列和消息循環,需要在線程中首先調用Looper.prepare()來創建消息隊列,然後調用Looper.loop()進入消息循環。

雖說 特定線程的消息只能分發給本線程,不能進行跨線程通訊,但是由於可以通過獲得線程的Looper對象來進行曲線的實現不同線程間消息的傳遞,代碼如下

package com.mytest.handlertest; 
import android.app.Activity; 
import android.graphics.Color; 
import android.os.Bundle; 
import android.os.Handler; 
import android.os.Looper; 
import android.os.Message; 
import android.util.Log; 
import android.view.View; 
import android.view.View.OnClickListener; 
import android.view.ViewGroup.LayoutParams; 
import android.widget.Button; 
import android.widget.LinearLayout; 
import android.widget.TextView; 
public class HandlerTest extends Activity implements OnClickListener{ 
     
    private String TAG = "HandlerTest"; 
    private boolean bpostRunnable = false; 
     
    private NoLooperThread noLooperThread = null;   
    private OwnLooperThread ownLooperThread = null;   
    private ReceiveMessageThread receiveMessageThread =null; 
     
    private Handler  mOtherThreadHandler=null; 
    private EventHandler mHandler = null;  
     
    private Button btn1 = null; 
    private Button btn2 = null; 
    private Button btn3 = null; 
    private Button btn4 = null; 
    private Button btn5 = null; 
    private Button btn6 = null; 
    private TextView tv = null; 
    /** Called when the activity is first created. */ 
    @Override 
    public void onCreate(Bundle savedInstanceState) { 
        super.onCreate(savedInstanceState); 
        
        LinearLayout layout = new LinearLayout(this); 
        LinearLayout.LayoutParams params = new LinearLayout.LayoutParams(250, 50); 
        layout.setOrientation(LinearLayout.VERTICAL); 
         
        btn1 = new Button(this); 
        btn1.setId(101); 
        btn1.setText("message from main thread self"); 
        btn1.setOnClickListener(this); 
        layout.addView(btn1, params); 
         
        btn2 = new Button(this); 
        btn2.setId(102); 
        btn2.setText("message from other thread to main thread"); 
        btn2.setOnClickListener(this); 
        layout.addView(btn2,params); 
         
        btn3 = new Button(this); 
        btn3.setId(103); 
        btn3.setText("message to other thread from itself"); 
        btn3.setOnClickListener(this); 
        layout.addView(btn3, params); 
         
        btn4 = new Button(this); 
        btn4.setId(104); 
        btn4.setText("message with Runnable as callback from other thread to main thread"); 
        btn4.setOnClickListener(this); 
        layout.addView(btn4, params); 
         
        btn5 = new Button(this); 
        btn5.setId(105); 
        btn5.setText("main thread's message to other thread"); 
        btn5.setOnClickListener(this); 
        layout.addView(btn5, params); 
         
        btn6 = new Button(this); 
        btn6.setId(106); 
        btn6.setText("exit"); 
        btn6.setOnClickListener(this); 
        layout.addView(btn6, params); 
         
        tv = new TextView(this); 
        tv.setTextColor(Color.WHITE); 
        tv.setText(""); 
        params = new LinearLayout.LayoutParams(LayoutParams.FILL_PARENT,LayoutParams.WRAP_CONTENT); 
        params.topMargin=10; 
        layout.addView(tv, params); 
         
        setContentView(layout); 
         
        receiveMessageThread = new ReceiveMessageThread(); 
        receiveMessageThread.start(); 
         
    } 
     
    class EventHandler extends Handler{ 
         
        public EventHandler(Looper looper){ 
            super(looper); 
        } 
         
        public EventHandler(){ 
            super(); 
        } 
        @Override 
        public void handleMessage(Message msg) { 
            // TODO Auto-generated method stub 
            super.handleMessage(msg); 
            Log.e(TAG, "CurrentThread id:----------+>" + Thread.currentThread().getId()); 
            switch(msg.what){ 
            case 1: 
                tv.setText((String)msg.obj); 
                break; 
                 
            case 2: 
                tv.setText((String)msg.obj); 
                noLooperThread.stop(); 
                break; 
                 
            case 3: 
                //不能在非主線程的線程裡面更新UI,所以這裡通過log打印信息 
                Log.e(TAG,(String)msg.obj); 
                ownLooperThread.stop(); 
                break; 
            default: 
                Log.e(TAG,(String)msg.obj); 
                break; 
            } 
        } 
         
    } 
     
      //ReceiveMessageThread has his own message queue by execute Looper.prepare();  
    class ReceiveMessageThread extends Thread { 
         
        @Override 
        public void run(){ 
            Looper.prepare(); 
            mOtherThreadHandler= new Handler(){ 
                @Override 
                public void handleMessage(Message msg) { 
                    // TODO Auto-generated method stub 
                    super.handleMessage(msg); 
                     
                    Log.e(TAG,"-------+>"+(String)msg.obj); 
                    Log.e(TAG, "CurrentThread id:----------+>" + Thread.currentThread().getId()); 
                     
                } 
                  
             }; 
             Log.e(TAG, "ReceiveMessageThread id:--------+>" + this.getId());  
             Looper.loop(); 
        } 
    } 
     
    class NoLooperThread extends Thread { 
        private EventHandler mNoLooperThreadHandler; 
        @Override 
        public void run() { 
             
            Looper myLooper = Looper.myLooper(); 
            Looper mainLooper= Looper.getMainLooper(); 
             
            String msgobj; 
            if(null == myLooper){ 
                //這裡獲得的是主線程的Looper,由於NoLooperThread沒有自己的looper所以這裡肯定會被執行 
                mNoLooperThreadHandler = new EventHandler(mainLooper); 
                msgobj = "NoLooperThread has no looper and handleMessage function executed in main thread!";  
            } else{ 
                mNoLooperThreadHandler = new EventHandler(myLooper); 
                msgobj = "This is from NoLooperThread self and handleMessage function executed in NoLooperThread!";  
            } 
             
            mNoLooperThreadHandler.removeMessages(0); 
             
            if(bpostRunnable == false){ 
            //send message to main thread 
                Message msg = mNoLooperThreadHandler.obtainMessage(2, 1, 1, msgobj); 
                mNoLooperThreadHandler.sendMessage(msg); 
                Log.e(TAG, "NoLooperThread id:--------+>" + this.getId());  
            }else{ 
                //下面new出來的實現了Runnable接口的對象中run函數是在Main Thread中執行,不是在NoLooperThread中執行 記得 null == myLooper麼 
                //注意Runnable是一個接口,它裡面的run函數被執行時不會再新建一個線程   
                //您可以在run上加斷點然後在eclipse調試中看它在哪個線程中執行   
                 
                mNoLooperThreadHandler.post(new Runnable(){ 
                    public void run() { 
                        // TODO Auto-generated method stub 
                        tv.setText("update UI through handler post runnalbe mechanism!");   
                        Log.e(TAG, "update UI id:--------+>" + Thread.currentThread().getId());  
                        noLooperThread.stop();   
                    } 
                     
                }); 
            } 
        } 
         
    } 
     
    class OwnLooperThread extends Thread{ 
        private EventHandler mOwnLooperThreadHandler = null; 
         
        @Override 
        public void run() { 
            Looper.prepare(); 
            Looper myLooper = Looper.myLooper(); 
            Looper mainLooper= Looper.getMainLooper(); 
             
            String msgobj; 
             
            if(null == myLooper){ 
                mOwnLooperThreadHandler = new EventHandler(mainLooper); 
                msgobj = "OwnLooperThread has no looper and handleMessage function executed in main thread!";  
            }else{ 
                mOwnLooperThreadHandler = new EventHandler(myLooper); 
                msgobj = "This is from OwnLooperThread self and handleMessage function executed in NoLooperThread!"; 
            } 
             
            mOwnLooperThreadHandler.removeMessages(0); 
             
            //給自己發送消息 
            Message msg = mOwnLooperThreadHandler.obtainMessage(3,1,1,msgobj); 
            mOwnLooperThreadHandler.sendMessage(msg); 
            Looper.loop(); 
        } 
    } 
     
    public void onClick(View v) { 
        // TODO Auto-generated method stub 
        switch(v.getId()){ 
        case 101: 
            //主線程發送消息給自己 
            Looper looper = Looper.myLooper();//get the Main looper related with the main thread  
            //如果不給任何參數的話會用當前線程對應的Looper(這裡就是Main Looper)為Handler裡面的成員mLooper賦值 
            mHandler = new EventHandler(looper); 
            // 清除整個MessageQueue裡的消息   
            mHandler.removeMessages(0); 
            String obj = "This main thread's message and received by itself!"; 
             
            Message msg = mHandler.obtainMessage(1,1,1,obj); 
            // 將Message對象送入到main thread的MessageQueue裡面  
            mHandler.sendMessage(msg); 
            break; 
        case 102: 
            //other線程發送消息給主線程 
            bpostRunnable = false; 
            noLooperThread = new NoLooperThread();   
            noLooperThread.start();   
            break; 
        case 103: 
             //other thread獲取它自己發送的消息   
            tv.setText("please look at the error level log for other thread received message");   
            ownLooperThread = new OwnLooperThread();   
            ownLooperThread.start();   
            break;   
        case 104:       
            //other thread通過Post Runnable方式發送消息給主線程   
            bpostRunnable = true;   
            noLooperThread = new NoLooperThread();   
            noLooperThread.start();   
            break; 
        case 105: 
            //主線程發送消息給other thread   
            if(null!=mOtherThreadHandler){   
            tv.setText("please look at the error level log for other thread received message from main thread");   
            String msgObj = "message from mainThread";   
            Message mainThreadMsg = mOtherThreadHandler.obtainMessage(1, 1, 1, msgObj);   
            mOtherThreadHandler.sendMessage(mainThreadMsg);   
            }   
            break;   
        case 106:   
            finish();   
            break;   
        } 
    } 

Copyright © Linux教程網 All Rights Reserved