一、什么是Handler
Handler是Android中引入的一种让开发者参与处理线程中消息循环的机制。每个Hanlder都关联了一个线程,每个线程内部都维护
了一个消息队列MessageQueue,这样Handler实际上也就关联了一个消息队列。可以通过Handler将Message和Runnable对象发
送到该Handler所关联线程的MessageQueue(消息队列)中,然后该消息队列一直在循环拿出一个Message,对其进行处理,处
理完之后拿出下一个Message,继续进行处理,周而复始。当创建一个Handler的时候,该Handler就绑定了当前创建Hanlder的线
程。从这时起,该Hanlder就可以发送Message和Runnable对象到该Handler对应的消息队列中,当从MessageQueue取出某个
Message时,会让Handler对其进行处理。
二、Handler作用
Handler可以用来在多线程间进行通信,在另一个线程中去更新UI线程中的UI控件只是Handler使用中的一种典型案例,除此之外,
Handler可以做很多其他的事情。每个Handler都绑定了一个线程,假设存在两个线程ThreadA和ThreadB,并且HandlerA绑定了
ThreadA,在ThreadB中的代码执行到某处时,出于某些原因,我们需要让ThreadA执行某些代码,此时我们就可以使用
Handler,我们可以在ThreadB中向HandlerA中加入某些信息以告知ThreadA中该做某些处理了。由此可以看出,Handler是
Thread的代言人,是多线程之间通信的桥梁,通过Handler,我们可以在一个线程中控制另一个线程去做某事。
下面的Handler是主线程中的Handler,因为其是在主线程中创建的,所以默认就是和主线程进行绑定的,通过一个延时的POST方法来进行UI的循环更新。
public class MainActivity extends AppCompatActivity {
private Handler handler = new Handler();
private int images[] = new int[]{R.drawable.im1, R.drawable.im2, R.drawable.im3};
private int index = 0;
private MyRunnable myRunnable = new MyRunnable();
private ImageView im_debug;
class MyRunnable implements Runnable{
@Override
public void run() {
index++;
index = index % 3;
im_debug.setImageResource(images[index]);
handler.postDelayed(myRunnable, 1000);
}
}
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
im_debug = (ImageView) findViewById(R.id.im_debug);
handler.postDelayed(myRunnable, 1000);
}
}
如下是Handler的两种绑定方式,一个和主线程进行绑定,一个和子线程进行绑定,这两个分别向主线程的Handler和子线程的
Handler发消息就可以得到得到其线程的ID,并且子线程中建立Looper
public class SecondActivity extends Activity {
private MyThread thread;
//默认是在主线程中执行
public Handler uiHandler = new Handler(){
@Override
public void handleMessage(Message msg) {
System.out.print("UI-----"+Thread.currentThread());
}
};
//在子线程中执行
class MyThread extends Thread{
public Handler hander;
public void run(){
Looper.prepare();
hander = new Handler(){
@Override
public void handleMessage(Message msg) {
System.out.print("CurrentID = "+Thread.currentThread());
}
};
Looper.loop();
}
}
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
TextView tv = new TextView(this);
tv.setText("hello Handler");
setContentView(tv);
thread = new MyThread();
thread.start();
try {
Thread.sleep(500);
} catch (InterruptedException e) {
e.printStackTrace();
}
//向子线程发消息
thread.hander.sendEmptyMessage(1);
//向主线程发消息
uiHandler.sendEmptyMessage(1);
}
}
HandlerThread建立的线程是在子线程中的,建立子线程的Handler的时候要绑定一个Looper
public class ThreeActivity extends Activity {
private HandlerThread thread;
private Handler handler;
private static final String TAG = "ThreeActivity";
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
TextView tv = new TextView(this);
tv.setText("Handler Thread Handler");
setContentView(tv);
//HandlerThread中使用了同步机制了
thread = new HandlerThread("handlerThread");
thread.start();
//如果looper为空,就处于等待的状态,直到Handler可以拿到looper对象
//这个是子线程的Handler
handler = new Handler(thread.getLooper()){
@Override
public void handleMessage(Message msg) {
System.out.print("当前线程:"+Thread.currentThread());
Log.i(TAG, "当前线程"+Thread.currentThread());
}
};
handler.sendEmptyMessage(1);
}
}
Handler提供了两种方式解决我们在本文一开始遇到的问题(在一个新线程中更新主线程中的UI控件),一种是通过post方法,一
种是调用sendMessage方法。
public class FiveActivity extends Activity {
private TextView tv_five;
private Handler handler = new Handler(){
@Override
public void handleMessage(Message msg) {
tv_five.setText("OK了方法2");
}
};
public void handler1(){
//这个是第一种方式来更新UI
//本质上也是发送message
handler.post(new Runnable() {
@Override
public void run() {
tv_five.setText("OK了方法1");
}
});
}
public void handler2(){
handler.sendEmptyMessage(1);
}
public void handler3(){
//内部还是通过UI机制
runOnUiThread(new Runnable() {
@Override
public void run() {
tv_five.setText("OK了方法3");
}
});
}
public void handler4(){
//
tv_five.post(new Runnable() {
@Override
public void run() {
tv_five.setText("OK了方法4");
}
});
}
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_five);
tv_five = (TextView) findViewById(R.id.tv_five);
new Thread(){
@Override
public void run() {
try {
Thread.sleep(2000);
//分别在此处调用不同的更新UI的方法
handler4();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}.start();
}
}
Handler.obtainMessage()来获得一个Message对象(Handler.obtainMessage()内部其实调用了Message.obtain())。
详细的介绍请参考下面两篇文章,写的很好:
http://blog.csdn.net/iispring/article/details/47115879
http://blog.csdn.net/iispring/article/details/47180325