A Handler allows you to send and process Message
and Runnable objects associated with a thread‘s MessageQueue
. Each Handler instance is associated with a single thread and that thread‘s message queue. When you create a new Handler, it is bound to the thread / message queue of the thread that is creating it -- from that point on, it will deliver messages and runnables to that message queue and execute them as they come out of the message queue.
There are two main uses for a Handler: (1) to schedule messages and runnables to be executed as some point in the future; and (2) to enqueue an action to be performed on a different thread than your own.
一个Handler允许你发送和处理消息(Message)以及与一个线程的消息队列相关的Runnable对象。每个Handler实例都和单个线程以及该线程的消息队列有关。当你创建了一个新Handler,它就会和创建它的线程/消息队列绑定,在那以后,它就会传递消息以及runnable对象给消息队列,然后执行它们。
需要使用Handler有两大主要的原因:
(1)在将来的某个时间点调度处理消息和runnable对象;
(2)将需要执行的操作放到其他线程之中,而不是自己的;
Scheduling messages is accomplished with the post(Runnable)
, postAtTime(Runnable, long)
, postDelayed(Runnable, long)
, sendEmptyMessage(int)
, sendMessage(Message)
, sendMessageAtTime(Message, long)
, and sendMessageDelayed(Message, long)
methods. The post versions allow you to enqueue Runnable objects to be called by the message queue when they are received; the sendMessage versions allow you to enqueue a Message
object containing a bundle of data that will be processed by the Handler‘s handleMessage(Message)
method (requiring that you implement a subclass of Handler).
调度处理消息是通过调用post(Runnable), postAtTime(Runnable, long),postDelayed(Runnable, long), sendEmptyMessage(int), sendMessage(Message),sendMessageAtTime(Message, long)和sendMessageDelayed(Message,long)等方法完成的。其中的post版本的方法可以让你将Runnable对象放进消息队列;sendMessage版本的方法可以让你将一个包含有bundle对象的消息对象放进消息队列,然后交由handleMessage(Message)方法处理。(这个需要你复写Handler的handleMessage方法)
When posting or sending to a Handler, you can either allow the item to be processed as soon as the message queue is ready to do so, or specify a delay before it gets processed or absolute time for it to be processed. The latter two allow you to implement timeouts, ticks, and other timing-based behavior.
When a process is created for your application, its main thread is dedicated to running a message queue that takes care of managing the top-level application objects (activities, broadcast receivers, etc) and any windows they create. You can create your own threads, and communicate back with the main application thread through a Handler. This is done by calling the same post or sendMessage methods as before, but from your new thread. The given Runnable or Message will then be scheduled in the Handler‘s message queue and processed when appropriate.
Handler在实际开发中是很常用的,主要是用来接收子线程发送的数据,然后主线程结合此数据来更新界面UI。
Android应用程序启动时,他会开启一个主线程(也就是UI线程),管理界面中的UI控件,进行事件派发。
你必需要知道的:
若在主线程中实例化一个Handler对象,例如:
Handler mHandler = newHandler();
此时它并没有新派生一个线程来执行此Handler,而是将此Handler附加在主线程上,故此时若你在Handler中执行耗时操作的话,还是会弹出ANR对话框!
- super.onCreate(savedInstanceState);
- setContentView(R.layout.main);
-
- mContext = this;
-
- Log.i(TAG, "Main thread id = " +
- Thread.currentThread().getId());
-
- btnStart = (Button) findViewById(R.id.btn_start);
- btnStart.setOnClickListener(this);
- btnStop = (Button) findViewById(R.id.btn_stop);
- btnStop.setOnClickListener(this);
- }
-
- @Override
- public void onClick(View view) {
- switch (view.getId()) {
- case R.id.btn_start:
- mHandler.postDelayed(workRunnable, DELAY_TIME);
- break;
- case R.id.btn_stop:
- mHandler.removeCallbacks(workRunnable);
- break;
- }
- }
- Runnable workRunnable = new Runnable() {
- int counter = 0;
-
- public void run() {
- if (counter++ < 1) {
- Log.i(TAG, "workRunnable thread id = " +
- Thread.currentThread().getId());
- mHandler.postDelayed(workRunnable, DELAY_TIME);
- }
- }
- };
-
- Handler mHandler = new Handler();
- }
- 发现thread id是相同的,这就说明:默认情况下创建的Handler会绑定到主线程上,你不能做太耗时的操作
- -----------------------------------------------------------------------------------------------------------------------
模式一、用HandlerThread来建新线程,
Handy class for starting a new thread that has a looper. The looper can then be used to create handler classes. Note that start() must still be called.
- public void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
- HandlerThread handlerThread = new HandlerThread("myHandlerThread");
- handlerThread.start();
- handler = new Handler(handlerThread.getLooper());
- handler.post(new MyRunnable());
- System.out.println("Oncreate---The Thread id is :"
- + Thread.currentThread().getId());
- setContentView(R.layout.main);
- }
- private class MyRunnable implements Runnable {
- public void run() {
- System.out.println("Runnable---The Thread is running");
- System.out.println("Runnable---The Thread id is :"
- + Thread.currentThread().getId());
- try {
- Thread.sleep(6000);
- } catch (InterruptedException e) {
-
- e.printStackTrace();
- }
- } 这个就是不同线程了
模式二、sendmessage,默认还是主线程,例子:
- Handler mHandler = new Handler() {
-
- @Override
- public void handleMessage(Message msg) {
- switch (msg.what) {
- case TASK_BEGIN:
- Log.i(TAG, "[H_TID:" +
- Thread.currentThread().getId() + "] Get TASK_BEGIN");
- break;
-
- case TASK_1:
- Log.i(TAG, "[H_TID:" +
- Thread.currentThread().getId() + "] Get TASK_1");
- break;
-
- case TASK_2:
- Log.i(TAG, "[H_TID:" +
- Thread.currentThread().getId() + "] Get TASK_2");
- break;
-
- case TASK_END:
- Log.i(TAG, "[H_TID:" +
- Thread.currentThread().getId() + "] Get TASK_END");
- finish();
- break;
- }
- super.handleMessage(msg);
- }
- };
- public void onClick(View view) {
- switch (view.getId()) {
- case R.id.btn_start:
-
- mHandler.sendEmptyMessage(TASK_BEGIN);
- Log.i(TAG, "Send TASK_BEGIN to handler.");
-
-
- Message msg1 = mHandler.obtainMessage(TASK_1);
- msg1.obj = "This is task1";
- mHandler.sendMessage(msg1);
- Log.i(TAG, "Send TASK_1 to handler.");
-
-
- Message msg2 = Message.obtain();
- msg2.arg1 = 10;
- msg2.arg2 = 20;
- msg2.what = TASK_2;
- mHandler.sendMessage(msg2);
- Log.i(TAG, "Send TASK_2 to handler.");
- break;
-
- case R.id.btn_stop:
-
- mHandler.sendEmptyMessageDelayed(TASK_END, 2000);
- Log.i(TAG, "Send TASK_END to handler.");
- break;
- }
- }
- } </span>
消息队列仍绑定在主线程上,但在子线程中发送消息。
- Thread workThread = new Thread() {
-
- @Override
- public void run() {
-
- mHandler.sendEmptyMessage(TASK_BEGIN);
- Log.i(TAG, "[S_TID:" + Thread.currentThread().getId() + "]" +
- "Send TASK_START to handler.");
-
-
- Message msg1 = mHandler.obtainMessage(TASK_1);
- msg1.obj = "This is task1";
- mHandler.sendMessage(msg1);
- Log.i(TAG, "[S_TID:" + Thread.currentThread().getId() + "]" +
- "Send TASK_1 to handler.");
-
-
- Message msg2 = Message.obtain();
- msg2.arg1 = 10;
- msg2.arg2 = 20;
- msg2.what = TASK_2;
- mHandler.sendMessage(msg2);
- Log.i(TAG, "[S_TID:" + Thread.currentThread().getId() + "]" +
- "Send TASK_2 to handler.");
-
-
- mHandler.sendEmptyMessageDelayed(TASK_END, 2000);
- Log.i(TAG, "[S_TID:" + Thread.currentThread().getId() + "]" +
- "Send TASK_END to handler.");
- }
- };
将消息队列绑定到子线程上,主线程只管通过Handler往子线程的消息队列中投递消息即可
- public void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
- setContentView(R.layout.main);
-
- Log.i(TAG, "[M_TID:" + Thread.currentThread().getId() + "]" +
- "This is in main thread.");
-
- HandlerThread myLooperThread = new HandlerThread("my looper thread");
- myLooperThread.start();
-
- Looper looper = myLooperThread.getLooper();
- mHandler = new MyHandler(looper);
-
-
- mHandler.sendEmptyMessage(TASK_BEGIN);
- Log.i(TAG, "[S_ID:" + Thread.currentThread().getId() + "]" +
- "Send TASK_START to handler.");
-
-
- Message msg1 = mHandler.obtainMessage(TASK_1);
- msg1.obj = "This is task1";
- mHandler.sendMessage(msg1);
- Log.i(TAG, "[S_ID:" + Thread.currentThread().getId() + "]" +
- "Send TASK_1 to handler.");
-
-
- Message msg2 = Message.obtain();
- msg2.arg1 = 10;
- msg2.arg2 = 20;
- msg2.what = TASK_2;
- mHandler.sendMessage(msg2);
- Log.i(TAG, "[S_ID:" + Thread.currentThread().getId() + "]" +
- "Send TASK_2 to handler.");
-
-
- mHandler.sendEmptyMessageDelayed(TASK_END, 2000);
- Log.i(TAG, "[S_ID:" + Thread.currentThread().getId() + "]" +
- "Send TASK_END to handler.");
- }
-
- class MyHandler extends Handler {
- public MyHandler(Looper looper) {
- super(looper);
- }
-
-
- @Override
- public void handleMessage(Message msg) {
- switch (msg.what) {
- case TASK_BEGIN:
- Log.i(TAG, "[H_TID:" +
- Thread.currentThread().getId() + "] Get TASK_BEGIN");
- break;
-
- case TASK_1:
- Log.i(TAG, "[H_TID:" +
- Thread.currentThread().getId() + "] Get TASK_1");
- break;
-
- case TASK_2:
- Log.i(TAG, "[H_TID:" +
- Thread.currentThread().getId() + "] Get TASK_2");
- break;
-
- case TASK_END:
- Log.i(TAG, "[H_TID:" +
- Thread.currentThread().getId() + "] Get TASK_END");
- finish();
- break;
- }
- super.handleMessage(msg);
- }
- }
- }
自己创建新的线程,然后在新线程中创建Looper,主线程调用子线程中的发消息方法,将消息发给子线程的消息队列
- super.onCreate(savedInstanceState);
- setContentView(R.layout.main);
-
- Log.i(TAG, "[M_TID:" + Thread.currentThread().getId() + "]" +
- "This is in main thread.");
-
- LooperThread testThread = new LooperThread();
- testThread.start();
-
-
- while (null == workHandler) {
- }
-
- testThread.sendMessageTodoYourWork();
- }
-
- class LooperThread extends Thread {
- @Override
- public void run() {
- Looper.prepare();
-
- workHandler = new Handler() {
-
- @Override
- public void handleMessage(Message msg) {
- switch (msg.what) {
- case TASK_BEGIN:
- Log.i(TAG, "[H_TID:" +
- Thread.currentThread().getId() + "] Get TASK_BEGIN");
- break;
-
- case TASK_1:
- Log.i(TAG, "[H_TID:" +
- Thread.currentThread().getId() + "] Get TASK_1");
- break;
-
- case TASK_2:
- Log.i(TAG, "[H_TID:" +
- Thread.currentThread().getId() + "] Get TASK_2");
- break;
-
- case TASK_END:
- Log.i(TAG, "[H_TID:" +
- Thread.currentThread().getId() + "] Get TASK_END");
- Looper.myLooper().quit();
- finish();
- break;
- }
- super.handleMessage(msg);
- }
- };
-
- Looper.loop();
- }
-
- public void sendMessageTodoYourWork() {
- Log.i(TAG, "[S_ID:" + Thread.currentThread().getId() + "]" +
- "Send TASK_START to handler.");
-
- workHandler.sendEmptyMessage(TASK_BEGIN);
-
- Log.i(TAG, "[S_ID:" + Thread.currentThread().getId() + "]" +
- "Send TASK_1 to handler.");
-
- Message msg1 = workHandler.obtainMessage(TASK_1);
- msg1.obj = "This is task1";
- workHandler.sendMessage(msg1);
-
- Log.i(TAG, "[S_ID:" + Thread.currentThread().getId() + "]" +
- "Send TASK_2 to handler.");
-
- Message msg2 = Message.obtain();
- msg2.arg1 = 10;
- msg2.arg2 = 20;
- msg2.what = TASK_2;
- workHandler.sendMessage(msg2);
-
- Log.i(TAG, "[S_ID:" + Thread.currentThread().getId() + "]" +
- "Send TASK_END to handler.");
-
- workHandler.sendEmptyMessageDelayed(TASK_END, 2000);
- }
- }
- }
、主/子线程均有一个消息队列,然后相互传递消息(这种方式是最灵活的,双向传递,也不复杂)
- public void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
- setContentView(R.layout.main);
-
- Log.i(TAG, "[M_TID:" + Thread.currentThread().getId() + "]" +
- "This is in main thread.");
-
- LooperThread testThread = new LooperThread();
- testThread.start();
-
-
- while (null == workHandler) {
- }
-
- testThread.sendMessageTodoYourWork();
- }
-
- Handler mainHandler = new Handler () {
-
- @Override
- public void handleMessage(Message msg) {
- switch (msg.what) {
- case TASK_BEGIN_OVER:
- Log.i(TAG, "[MH_TID:" +
- Thread.currentThread().getId() + "] TASK_BEGIN_OVER");
- break;
-
- case TASK_1_OVER:
- Log.i(TAG, "[MH_TID:" +
- Thread.currentThread().getId() + "] TASK_1_OVER");
- break;
-
- case TASK_2_OVER:
- Log.i(TAG, "[MH_TID:" +
- Thread.currentThread().getId() + "] TASK_2_OVER");
- break;
-
- case TASK_END_OVER:
- Log.i(TAG, "[MH_TID:" +
- Thread.currentThread().getId() + "] TASK_END_OVER");
- finish();
- break;
- }
- super.handleMessage(msg);
- }
- };
-
- class LooperThread extends Thread {
- @Override
- public void run() {
- Looper.prepare();
-
- workHandler = new Handler() {
-
- @Override
- public void handleMessage(Message msg) {
- switch (msg.what) {
- case TASK_BEGIN:
- Log.i(TAG, "[ZH_TID:" +
- Thread.currentThread().getId() + "] Get TASK_BEGIN");
-
- mainHandler.sendEmptyMessage(TASK_BEGIN_OVER);
- break;
-
- case TASK_1:
- Log.i(TAG, "[ZH_TID:" +
- Thread.currentThread().getId() + "] Get TASK_1");
-
- mainHandler.sendEmptyMessage(TASK_1_OVER);
- break;
-
- case TASK_2:
- Log.i(TAG, "[ZH_TID:" +
- Thread.currentThread().getId() + "] Get TASK_2");
-
- mainHandler.sendEmptyMessage(TASK_2_OVER);
- break;
-
- case TASK_END:
- Log.i(TAG, "[ZH_TID:" +
- Thread.currentThread().getId() + "] Get TASK_END");
- Looper.myLooper().quit();
-
- mainHandler.sendEmptyMessage(TASK_END_OVER);
- Looper.myLooper().quit();
- break;
- }
- super.handleMessage(msg);
- }
- };
-
- Looper.loop();
- }
-
- public void sendMessageTodoYourWork() {
- Log.i(TAG, "[ZS_ID:" + Thread.currentThread().getId() + "]" +
- "Send TASK_START to handler.");
-
- workHandler.sendEmptyMessage(TASK_BEGIN);
-
- Log.i(TAG, "[ZS_ID:" + Thread.currentThread().getId() + "]" +
- "Send TASK_1 to handler.");
-
- Message msg1 = workHandler.obtainMessage(TASK_1);
- msg1.obj = "This is task1";
- workHandler.sendMessage(msg1);
-
- Log.i(TAG, "[ZS_ID:" + Thread.currentThread().getId() + "]" +
- "Send TASK_2 to handler.");
-
- Message msg2 = Message.obtain();
- msg2.arg1 = 10;
- msg2.arg2 = 20;
- msg2.what = TASK_2;
- workHandler.sendMessage(msg2);
-
- Log.i(TAG, "[ZS_ID:" + Thread.currentThread().getId() + "]" +
- "Send TASK_END to handler.");
-
- workHandler.sendEmptyMessageDelayed(TASK_END, 2000);
- }
- }