今天在学习Android时遇到了Handler。在Android的多线程操作时不要阻塞ui线程,不要在ui线程外访问Android UI包。这时需要用到Handler,它运行在主线程中,通过接收子线程的消息来配合主线程更新UI。
下面是一个方便理解的例子:
模拟一个下载过程:
如果直接在子线程中改变UI(download为下载按钮触发事件):
public void download(View view){
//使用线程模拟下载操作
textView.setText("正在下载中....");
new Thread(new Runnable() {
@Override
public void run() {
try {
Thread.sleep(3000);
} catch (InterruptedException e) {
e.printStackTrace();
}
textView.setText("下载完毕");
}
}).start();
}
这样做会报错,这时我们就需要用到Handler,使用Handler在子线程中发出信号,当主线程收到信号后在改变UI:
private Handler handler=new Handler(){
@Override
public void handleMessage(Message msg) {
super.handleMessage(msg);
switch (msg.what) {
case (10):
textView.setText("正在下载中....") ;
break;
case (100):
textView.setText("下载完毕");
break;
}
}
};
public void download(View view){
//使用线程模拟下载操作
//textView.setText("正在下载中....");
handler.sendEmptyMessage(10);//发送一个空消息.相当于一个标记
new Thread(new Runnable() {
@Override
public void run() {
try {
Thread.sleep(3000);
} catch (InterruptedException e) {
e.printStackTrace();
}
// textView.setText("下载完毕");
handler.sendEmptyMessage(100);//发送一个空消息.相当于一个标记
}
}).start();
}
Handler实现原理:
1.Message对象,表示要传递的消息,使用链表创建消息池,避免大量创建消息对象
2.MessageQueue对象,存放消息对象的消息列,先进先出
3.Looper:管理当前消息队列,取出Message对象,传入handlerMessage方法
4.Handler对象负责把Message对象push到MessageQueue中以及接受Loop取出的消息
Android启动程序时会在UI线程创建一个MessageQueue
应注意,在使用handler时有时会出现内存泄漏问题。