Handler in Android Development

By | 2013 年 4 月 2 日

Handler是在Android系统中用来做消息分发和处理的类。在涉及到跨线程调用的时候,可以使用这个组件。
Handler is used for message dispatch and process. It’s useful to dealing with inter-thread communication.

每一个Handler绑定在一个Looper上,Looper可以理解为一个线程中的消息循环,上面有一个消息队列MessageQueue。Looper每次从消息队列取一个消息Message,然后让Handler去处理,然后再去取一个消息,继续处理这样子。
Each handler is attached to a Looper. Looper can be seen as a message loop in a thread, and in the thread, there is a MessageQueue. Looper will pick a message from the queue, and let the handler to handle the message, and then pick next message, let handler to process, ….., and so on.

系统会为每一个Activity自动创建一个Looper进行消息循环的处理。如果是自己创建的线程,默认是没有Looper的,可以通过Looper.prepare()和Looper.loop()来给调用线程加上一个消息循环。
System will create an Looper for Activity automatically. And if you create your own Thread, by default there is no Looper on it. But you can call Looper.prepare() and Looper.loop() in the thread to initialize an looper for it. See the code below:



给自定义线程添加消息循环
Add a looper to a thread

class LooperThread extends Thread {
      public Handler mHandler;

      public void run() {
          //Initialize the current thread as a looper. 
          //This gives you a chance to create handlers that then reference this looper, before actually starting the loop. 
          //Be sure to call loop() after calling this method, and end it by calling quit().
          Looper.prepare();

          //the handler will attach to the thread in which it was created.
          mHandler = new Handler() {
              public void handleMessage(Message msg) {
                  // process incoming messages here
              }
          };

          //Run the message queue in this thread. Be sure to call quit() to end the loop.
          Looper.loop();
      }
  }



一个用Handler来进行UI更新的例子
An example to use handler update UI

From:http://www.pin5i.com/showtopic-android-handler.html

public class MyHandlerActivity extends Activity {
    Button button;
    MyHandler myHandler;

    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.handlertest);

        button = (Button) findViewById(R.id.button);
        myHandler = new MyHandler();
        // 当创建一个新的Handler实例时, 它会绑定到当前线程和消息的队列中,开始分发数据
        // Handler有两个作用, (1) : 定时执行Message和Runnalbe 对象
        // (2): 让一个动作,在不同的线程中执行.

        // 它安排消息,用以下方法
        // post(Runnable)
        // postAtTime(Runnable,long)
        // postDelayed(Runnable,long)
        // sendEmptyMessage(int)
        // sendMessage(Message);
        // sendMessageAtTime(Message,long)
        // sendMessageDelayed(Message,long)
       
        // 以上方法以 post开头的允许你处理Runnable对象
        //sendMessage()允许你处理Message对象(Message里可以包含数据,)

        MyThread m = new MyThread();
        new Thread(m).start();
    }

    /**
     * 接受消息,处理消息 ,此Handler会与当前主线程一块运行
     * */

    class MyHandler extends Handler {
        public MyHandler() {
        }

        public MyHandler(Looper L) {
            super(L);
        }

        // 子类必须重写此方法,接受数据
        @Override
        public void handleMessage(Message msg) {
            // TODO Auto-generated method stub
            Log.d("MyHandler", "handleMessage......");
            super.handleMessage(msg);
            // 此处可以更新UI
            Bundle b = msg.getData();
            String color = b.getString("color");
            MyHandlerActivity.this.button.append(color);

        }
    }

    class MyThread implements Runnable {
        public void run() {

            try {
                Thread.sleep(10000);
            } catch (InterruptedException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }

            Log.d("thread.......", "mThread........");
            Message msg = new Message();
            Bundle b = new Bundle();// 存放数据
            b.putString("color", "我的");
            msg.setData(b);

            MyHandlerActivity.this.myHandler.sendMessage(msg); // 向Handler发送消息,更新UI

        }
    }

}



补充一点,同一个Message不能发给两个Handler,那样会报错:AndroidRuntimeException:This message is already in use。如果要广播消息,可以这么做:

// clone a message from the message want to broadcast
Message cloneMessage = Message.obtain(originalMessage);
// send the cloned message to other handlers
anotherHandler.postMessage(cloneMessage);
// send the original message to the handler where it should be posted.
originalHandler.postMessage(originalMessage);



参考 | Reference
http://developer.android.com/intl/zh-CN/reference/android/os/Handler.html
http://developer.android.com/intl/zh-CN/reference/android/os/Looper.html
http://www.pin5i.com/showtopic-android-handler.html

发表评论

电子邮件地址不会被公开。 必填项已用*标注