Android 中 Handler 消息传递机制

来源:互联网 发布:北大青鸟软件编程 编辑:程序博客网 时间:2024/04/28 02:54

---------------------------------------------------------------------------------------------------------------------------------------------------------------------------

在 Android 平台中,新启动的线程是无法访问 Activity 里的 Widget 的,当然也不能将运行的状态送出来,这就需要有 Handler 机制进行消息的传递了,

Handler 的主要功能是完成 Activity 的 Widget 与应用程序中线程之间的交互。

开发事实有 Handler 类的程序步骤如下:

1,在 Activity 或 Activity 的 Widget 中创建 Handler 类的对象,并重写 handleMessage 方法。

2,在新启动的线程中调用 sendEmptyMessage 或者 sendMessage 方法向 Handler 发送消息。

3,Handler 类的对象用 handleMessage 方法接收消息,然后根据消息的不同执行不同的操作。

下面举一个换图程序的例子。

主要逻辑代码

[java] view plaincopy
  1. package wyf.ytl;  
  2.   
  3. import android.app.Activity;  
  4. import android.os.Bundle;  
  5. import android.os.Handler;  
  6. import android.os.Message;  
  7. import android.widget.ImageView;  
  8.   
  9. public class SampleHandler extends Activity {  
  10.     ImageView myImageView;  
  11.     Handler myHandler = new Handler(){  
  12.         @Override  
  13.         public void handleMessage(Message msg) {  
  14.             switch(msg.what){  
  15.             case 0:  
  16.                 myImageView.setImageResource(R.drawable.bbta);break;  
  17.             case 1:  
  18.                 myImageView.setImageResource(R.drawable.bbtb);break;  
  19.             case 2:  
  20.                 myImageView.setImageResource(R.drawable.bbtc);break;  
  21.             case 3:  
  22.                 myImageView.setImageResource(R.drawable.bbtd);break;      
  23.             }  
  24.             super.handleMessage(msg);  
  25.         }  
  26.     };  
  27.     @Override  
  28.     public void onCreate(Bundle savedInstanceState) {  
  29.         super.onCreate(savedInstanceState);  
  30.         setContentView(R.layout.main);  
  31.         myImageView = (ImageView) findViewById(R.id.myImageView);  
  32.         MyThread myThread = new MyThread(this);  
  33.         myThread.start();  
  34.     }  
  35.   

换图线程类

[java] view plaincopy
  1. package wyf.ytl;  
  2. public class MyThread extends Thread{  
  3.     SampleHandler activity;  
  4.     int what = 1;  
  5.     public MyThread(SampleHandler activity){  
  6.         this.activity = activity;  
  7.     }  
  8.     @Override  
  9.     public void run() {  
  10.         while(true){  
  11.             activity.myHandler.sendEmptyMessage((what++)%4);  
  12.             try{  
  13.                 Thread.sleep(2000);  
  14.             }  
  15.             catch(Exception e){  
  16.                 e.printStackTrace();  
  17.             }  
  18.         }  
  19.     }  
  20. }  
当然这里需要在 res/drawable中添加图片资源,并且编写相就的 main.xml 文件
[html] view plaincopy
  1. <?xml version="1.0" encoding="utf-8"?>  
  2. <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"  
  3.     android:orientation="vertical"  
  4.     android:layout_width="fill_parent"  
  5.     android:layout_height="fill_parent"  
  6.     android:gravity="center"    >  
  7. <ImageView    
  8.     android:id="@+id/myImageView"   
  9.     android:layout_width="fill_parent"   
  10.     android:layout_height="wrap_content"   
  11.     android:src="@drawable/bbta"   
  12.     android:gravity="center"  />  
  13. </LinearLayout> 

运行程序观察运行效果,会每隔两秒钟更换一张图片。

---------------------------------------------------------------------------------------------------------------------------------------------------------------------------

(1)在同一个Activity中 再定义一个private final Handler mHandler = new Handler();

(2)在同一个Activity中 先定义一个Runnable

Runnable mUpdateTimer = new Runnable() {
        public void run() {
            updateTimerView();
        }
    };

(3)在同一个Activity中 再定义一个updateTimerView()

private void updateTimerView() {
        long timer = 0;
        switch (mState) {
        case RECORDER_STARTED:
                if (lastState == RECORDER_PAUSED)
                    mHandler.postDelayed(mUpdateTimer, 1000 * looperTimes
                            - currentTime);
                else
                    mHandler.postDelayed(mUpdateTimer, 1000 * (++looperTimes)- currentTime);
                timer = (currentTime + 500) / 1000;
            break;
        case RECORDER_IDLE:
           break;
        case RECORDER_CREATED:
            timer = 0;
            break;

}

(4) Handler 类说明

public final boolean postDelayed(Runnable r, long delayMillis)

Added in API level 1

Causes the Runnable r to be added to the message queue, to be run after the specified amount of time elapses. The runnable will be run on the thread to which this handler is attached.

Parameters
rThe Runnable that will be executed.delayMillisThe delay (in milliseconds) until the Runnable will be executed.
Returns
  • Returns true if the Runnable was successfully placed in to the message queue. Returns false on failure, usually because the looper processing the message queue is exiting. Note that a result of true does not mean the Runnable will be processed -- if the looper is quit before the delivery time of the message occurs then the message will be dropped.

---------------------------------------------------------------------------------------------------------------------------------------------------------------------------

(1)    class myHandler extends Handler {
        @Override
        public void handleMessage(Message msg) {
            int type = msg.what;
            switch (type) {
            case MSG_DRAG_BACK:
                break;
            case SAVE:
                break;
           case PAUSE_TIMER:
                break;
            case ENABLE_CLICKBUTTON:
                 break;
            }
        }
    }
(2)private myHandler syhHandler;
(3)public void useMyHandler(){
if (syhHandler == null) {
                    syhHandler = new myHandler();
}
Message msg = syhHandler.obtainMessage(ENABLE_CLICKBUTTON);
syhHandler.removeMessages(ENABLE_CLICKBUTTON);
syhHandler.sendMessageDelayed(msg, 1000);
}

--------------------------------------------------------------------------------------------------------------------------------------------------------------------------

(1)public AudioService(Context context) {
......
createAudioSystemThread();
......
}
(2)private void createAudioSystemThread() {
        mAudioSystemThread = new AudioSystemThread();
        mAudioSystemThread.start();
        waitForAudioHandlerCreation();
}
    /** Waits for the volume handler to be created by the other thread. */
(3)private void waitForAudioHandlerCreation() {
        synchronized(this) {
            while (mAudioHandler == null) {
                try {
                    // Wait for mAudioHandler to be set by the other thread
                    wait();
                } catch (InterruptedException e) {
                    Log.e(TAG, "Interrupted while waiting on volume handler.");
                }
            }
        }
    }
(4)/** Thread that handles native AudioSystem control. */
    private class AudioSystemThread extends Thread {
        AudioSystemThread() {
            super("AudioService");
        }
        @Override
        public void run() {
            // Set this thread up so the handler will work on it
            Looper.prepare();
            synchronized(AudioService.this) {
                mAudioHandler = new AudioHandler();
                // Notify that the handler has been created
                AudioService.this.notify();
            }
            // Listen for volume change requests that are set by VolumePanel
            Looper.loop();
        }
(5) /** Handles internal volume messages in separate volume thread. */
    private class myHandler extends Handler {
        private void userDefinedfuntionTest1() {
            ........
            // Post a persist msg
            sendMsg();
        }
        private void userDefinedfuntionTest2() {
            .......
            // Post a persist msg
            sendMsg();
        }
        private void userDefinedfuntionTest1() {
            ........
        }
        private void userDefinedfuntionTest2() {
            .......
            
        }
        @Override
        public void handleMessage(Message msg) {
            switch (msg.what) {
                case MSG_ONE:
                    break;
                case MSG_TWO:
                    break;
                case MSG_THREE:
                    break;
                case MSG_FOURCE:
                    break;
                case MSG_SIX:
                    break;
            }
        }
    }
(6)private static void sendMsg(Handler handler, int msg, int existingMsgPolicy, int arg1, int arg2, Object obj, int delay) {
        if (existingMsgPolicy == SENDMSG_REPLACE) {
            handler.removeMessages(msg);
        } else if (existingMsgPolicy == SENDMSG_NOOP && handler.hasMessages(msg)) {
            Log.d(TAG, "sendMsg: Msg " + msg + " existed!");
            return;
        }
        handler.sendMessageDelayed(handler.obtainMessage(msg, arg1, arg2, obj), delay);
    }
(7)Handler的sendMessageDelayed (Message msg, long delayMillis) 说明:
public final boolean sendMessageDelayed (Message msg, long delayMillis)
Added in API level 1
Enqueue a message into the message queue after all pending messages before (current time + delayMillis).
You will receive it in handleMessage(Message), in the thread attached to this handler.
Returns
Returns true if the message was successfully placed in to the message queue.
Returns false on failure, usually because the looper processing the message queue is exiting.
Note that a result of true does not mean the message will be processed --
 if the looper is quit before the delivery time of the message occurs then the message will be dropped.

---------------------------------------------------------------------------------------------------------------------------------------------------------------------------


原创粉丝点击