Android中的Handler机制
在android主线程中做太耗时的操作会引起ANR崩溃,为了进行线程间通信,就需要用到handler消息处理机制。消息传递分为两类,一种是从MainThread向WorkerThread传递消息,而另外一种是从WorkerThread向MainThread传递消息。由于主线程主要负责UI相关的事件,如用户的点击事件,屏幕触摸事件等,当捕捉到用户动作后将会分发到相应的组件进行处理。因此,主线程也叫UI线程。
首先,我来说一下handler工作流程。还是用流程图的方式来表示,这样看起来一目了然。
handler(发送消息)➡MessageQueue(消息队列)➡Looper(取出消息)➡交给handler(调用handlerMessage方法去处理)➡更新UI界面
简单地总结一下,就是在子线程中通过handler去发送一条消息到主线程,这条消息就会进入到消息队列MessageQueue中,然后在主线程中调用Looper对象来管理消息队列,不断的从消息队列中取出消息,并将消息分给对应的Handler来处理,最后更新UI界面。
- 从WorkThread向MainThread发送消息
1 package com.example.handlertest; 2 3 import android.app.Activity; 4 import android.os.Bundle; 5 import android.os.Handler; 6 import android.os.Message; 7 import android.view.Menu; 8 import android.view.View; 9 import android.view.View.OnClickListener; 10 import android.widget.Button; 11 import android.widget.TextView; 12 13 public class MainActivity extends Activity { 14 15 private Button mybutton; 16 private TextView mytextview; 17 private Handler handler; 18 @Override 19 protected void onCreate(Bundle savedInstanceState) { 20 super.onCreate(savedInstanceState); 21 setContentView(R.layout.activity_main); 22 mytextview=(TextView)findViewById(R.id.textview1); 23 mybutton=(Button)findViewById(R.id.button1); 24 mybutton.setOnClickListener(new ButtonListener()); 25 handler=new firstHandler(); 26 } 27 //不能直接在WorkerThread中去更新UI,所以使用handler来处理 28 class firstHandler extends Handler 29 { 30 @Override 31 public void handleMessage(Message msg) { 32 // TODO 在textview中显示获取到的数据 33 super.handleMessage(msg); 34 System.out.println("handlerMessage--->"+Thread.currentThread().getName()); 35 String ss=(String)msg.obj; 36 mytextview.setText(ss); 37 } 38 } 39 class ButtonListener implements OnClickListener 40 { 41 @Override 42 public void onClick(View v) { 43 // TODO Auto-generated method stub 44 Thread td=new NetWorkThread(); 45 td.start(); 46 } 47 } 48 //开启一个子线程WorkerThread 49 class NetWorkThread extends Thread 50 { 51 @Override 52 public void run() { 53 // TODO 让线程休眠2s,利用handler向主线程发送消息 54 System.out.println("handlerMessage--->"+Thread.currentThread().getName()); 55 super.run(); 56 try 57 { 58 Thread.sleep(1*1000); 59 } 60 catch(InterruptedException e) 61 { 62 e.printStackTrace(); 63 } 64 String s="全家福"; 65 Message msg=handler.obtainMessage(); 66 msg.obj=s; 67 handler.sendMessage(msg); 68 } 69 } 70 }
- 从MainThread向WorkerThread发送消息
1 package com.example.s2_e2; 2 3 import android.app.Activity; 4 import android.os.Bundle; 5 import android.os.Handler; 6 import android.os.Looper; 7 import android.os.Message; 8 import android.view.View; 9 import android.view.View.OnClickListener; 10 import android.widget.Button; 11 import android.widget.TextView; 12 13 public class MainActivity extends Activity { 14 15 private Button button1; 16 private Handler handler; 17 @Override 18 protected void onCreate(Bundle savedInstanceState) { 19 super.onCreate(savedInstanceState); 20 setContentView(R.layout.activity_main); 21 22 button1=(Button)findViewById(R.id.button1); 23 button1.setOnClickListener(new ButtonListener()); 24 WorkerThread wd=new WorkerThread(); 25 wd.start(); 26 } 27 class ButtonListener implements OnClickListener 28 { 29 30 @Override 31 public void onClick(View v) { 32 33 System.out.println("clickThread is--->"+Thread.currentThread().getName()); 34 Message msg=handler.obtainMessage(); 35 handler.sendMessage(msg); 36 } 37 38 } 39 40 class WorkerThread extends Thread 41 { 42 @Override 43 public void run() { 44 //准备Looper对象 45 Looper.prepare(); 46 //在WorkThread当中生成一个Handler对象 47 handler=new Handler(){ 48 @Override 49 public void handleMessage(Message msg) { 50 51 System.out.println("receive message--->"+Thread.currentThread().getName()); 52 } 53 }; 54 //Looper对象不断的从消息队列中取出消息对象,使用Handler的sendMessage来处理消息对象 55 //若没有消息则会发生阻塞 56 Looper.loop(); 57 } 58 59 } 60 }
另外,不得不提的是Handler的Post方法。
1 package com.example.s2_e2; 2 3 import android.app.Activity; 4 import android.os.Bundle; 5 import android.os.Handler; 6 import android.os.Message; 7 import android.view.View; 8 import android.view.View.OnClickListener; 9 import android.widget.Button; 10 import android.widget.TextView; 11 12 public class MainActivity extends Activity { 13 14 //问题1.如何把一个Runnable对象放置在消息队列中? 15 //问题2.Looper取出了带有r的Message对象之后,做了什么? 16 private Button button1; 17 Handler handler=new Handler(); 18 @Override 19 protected void onCreate(Bundle savedInstanceState) { 20 super.onCreate(savedInstanceState); 21 setContentView(R.layout.activity_main); 22 23 button1=(Button)findViewById(R.id.button1); 24 button1.setOnClickListener(new ButtonListener()); 25 } 26 class ButtonListener implements OnClickListener 27 { 28 @Override 29 public void onClick(View arg0) { 30 MyThread td=new MyThread(); 31 td.start(); 32 } 33 } 34 class MyThread extends Thread 35 { 36 @Override 37 public void run() { 38 Runnable r=new Runnable() 39 { 40 @Override 41 public void run() { 42 //这里可以写更新UI的内容 43 System.out.println("currentThread is"+MyThread.currentThread().getName()); 44 } 45 }; 46 //1:该方法生成了一个Message对象,将r赋值给Message对象的callback属性,把Message对象放到消息队列中 47 //2:取出Message对象之后调用了dispatchMessage方法。由于callback不为空,所以执行了msg.callback方法 48 handler.post(r); 49 } 50 } 51 }