Handler可以声明在主线程可以声明在新开的线程,只不过在新开的线程定义handler要自己创建一个Looper对象,并通过prepare()启动它。在ui线程中系统已经初始化了一个Looper对象。
先看定义在主线程的情况:
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
final Handler handler = new Handler(){
public void handleMessage(Message msg){
if(msg.what==123){
Bundle bundle=msg.getData();
int i=bundle.getInt("i");
Toast.makeText(getApplicationContext(),"handler 测试成功 "+i,Toast.LENGTH_SHORT).show();
}
}
};
new Timer().schedule(new TimerTask() {
@Override
public void run() {
int i=5;
Message message=new Message();
Bundle bundle=new Bundle();
bundle.putInt("i",i);
message.setData(bundle);
message.what=123;
handler.sendMessage(message);
}
},0,1200);
这里定义了一个Timer来启动一条新线程以周期性的执行任务。
Looper:每个线程只能有一个Looper,它的loop方法负责读取MessageQueue中的消息,读到信息之后就把信息交给发送该消息的handler进行处理。
现在来看在子线程定义handler的情况:
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
button=(Button)findViewById(R.id.btn);
mes msg=new mes("来自主线程");
final Message message=new Message();
message.what=123;
Bundle bundle=new Bundle();
bundle.putSerializable("msg", msg);
message.setData(bundle);
final MyThread myThread=new MyThread();
myThread.start();
button.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
myThread.handler.sendMessage(message);
}
});
}
class MyThread extends Thread{
public Handler handler;
public void run(){
Looper.prepare();
handler=new Handler(){
public void handleMessage(Message message){
if(message.what==123){
Bundle bundle=message.getData();
mes msg=new mes();
msg=(mes)bundle.getSerializable("msg");
Toast.makeText(MainActivity.this,"测试成功 "+msg.getText(),Toast.LENGTH_SHORT).show();
}
}
};
Looper.loop();
}
}
mes类
public class mes implements Serializable{
String text;
public mes() {
}
public mes(String text) {
this.text = text;
}
public String getText() {
return text;
}
public void setText(String text) {
this.text = text;
}
}
这里值得注意的是如果不设个按钮事件,而是直接将myThread.handler.sendMessage(message);写在myThread.start()后面会报出空指针异常。