一、Handler、Message、MessageQueue与Looper介绍
1、Message:消息;其中包含了消息ID,消息对象以及处理的数据等,由MessageQueue统一列队,终由Handler处理
Handler:处理者;负责Message发送消息及处理。Handler通过与Looper进行沟通,从而使用Handler时,需要实现handlerMessage(Message msg)方法来对特定的Message进行处理,例如更新UI等(主线程中才行)
2、MessageQueue:消息队列;用来存放Handler发送过来的消息,并按照FIFO(先入先出队列)规则执行。当然,存放Message并非实际意义的保存,而是将Message以链表的方式串联起来的,等Looper的抽取。
3、Looper:消息泵,不断从MessageQueue中抽取Message执行。因此,一个线程中的MessageQueue需要一个Looper进行管理。Looper是当前线程创建的时候产生的(UI Thread即主线程是系统帮忙创建的Looper,而如果在子线程中,需要手动在创建线程后立即创建Looper[调用Looper.prepare()方法])。也就是说,会在当前线程上绑定一个Looper对象。
4、Thread:线程;负责调度消息循环,即消息循环的执行场所。
a)handler应该由处理消息的线程创建。
b)handler与创建它的线程相关联,而且也只与创建它的线程相关联。handler运行在创建它的线程中,所以,如果在handler中进行耗时的操作,会阻塞创建它的线程。
二、Handler实例
public class HandlerConstructorTest extends Activity {
private Handler handler1 = new Handler(new Callback() {
@Override
public boolean handleMessage(Message msg) {
System.out.println("使用了Handler1中的接口Callback");
return false; // 此处,如果返回 false,下面的 handlerMessage方法会执行,true ,下面的不执行
}
});
private Handler handler2 = new Handler() {
public void handleMessage(Message msg) {
System.out.println("Handler2");
}
};
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
//消息1
Message obtain1 = Message.obtain();
obtain1.obj = "sendMessage";
obtain1.what = 1;
handler1.sendMessage(obtain1);
//消息2
Message obtain2 = handler2.obtainMessage();
handler2.sendMessage(obtain2); //①
// handler2.dispatchMessage(obtain2); //②
}
}
三、Handler使用场景
场景一:
在主线程中创建Handler,其中复写了handlerMessager方法(处理message,更新界面)
然后创建子线程,其中创建Message对象,并设置消息,通过handler发送消息
public class MainActivity2 extends Activity implements OnClickListener{
private Button bt_send;
private TextView tv_recieve;
private Handler handler = new Handler(){
@Override
public void handleMessage(Message msg) {
super.handleMessage(msg);
tv_recieve.setText((String) msg.obj);
}
};
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
bt_send = (Button) findViewById(R.id.bt_send);
tv_recieve = (TextView) findViewById(R.id.tv_recieve);
bt_send.setOnClickListener(this);
tv_recieve.setOnClickListener(this);
}
@Override
public void onClick(View v) {
switch (v.getId()) {
case R.id.bt_send:
new Thread(){
public void run() {
Message msg = new Message();
msg.obj = "消息来了"+ System.currentTimeMillis();
handler.sendMessage(msg);
}
}.start();
break;
}
}
}
场景二:
创建两个子线程,一个线程中创建Handler并进行处理消息,另一个线程使用handler发送消息。
public class MainActivity extends Activity implements OnClickListener{
private Button bt_send;
private TextView tv_recieve;
private Handler handler;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
bt_send = (Button) findViewById(R.id.bt_send);
tv_recieve = (TextView) findViewById(R.id.tv_recieve);
bt_send.setOnClickListener(this);
tv_recieve.setOnClickListener(this);
new Thread(){
public void run() {
//Looper.prepare();
handler = new Handler(Looper.getMainLooper()){
@Override
public void handleMessage(Message msg) {
super.handleMessage(msg);
tv_recieve.setText((String) msg.obj);
}
};
//Looper.loop();
}
}.start();
}
@Override
public void onClick(View v) {
switch (v.getId()) {
case R.id.bt_send:
new Thread(){
public void run() {
Message msg = new Message();
msg.obj = "消息来了"+ System.currentTimeMillis();
handler.sendMessage(msg);
}
}.start();
break;
}
}
}
在子线程中是不能更新界面的操作的,只能放在主线程中进行更新。所以必须将处理的消息放到主线程中,才能进行更新界面,否则会报错。