最近完成了一个多媒体播放器,更新UI的时候,使用handler遇到了一点问题,就自己再去研究了一下,学学大家分享哈学习心得。
Handler 机制
Handler主要用于从子线程去更新UI线程(即主线程)。因为android 中明确规定不能从子线程去直接更新UI,否则会报错的哦,这时候我们就可以使用Handler去更新了。下面是我常用使用handler更新UI的几种方式:
(一)废话不说直接上代码:
首先我们创建一个handler 重写它的handleMessage方法。
private Thread th_current;
private final int SUCCESS = 0;
private final int ERRSOR = 1;
@SuppressLint("HandlerLeak")
private Handler handle = new Handler(){
@Override
public void handleMessage(Message msg) {
// TODO Auto-generated method stub
switch (msg.what) {
case SUCCESS:
txt_infos.setText("哇,成功了啊!");
break;
case ERRSOR:
txt_infos.setText("no,居然出错了!!");
break;
default:
break;
}
}
};
接着咱们来初始化一个Thread子线程。
public void getThread(){
th_current = new Thread(new Runnable() {
@Override
public void run() {
// TODO Auto-generated method stub
/*这里我们可以处理一些费时操作
*操作完成后我们可以同message对象返回一些信息
*/
Message msg = new Message();
// msg.obj = 这可以是一个对象; //我这测试没有什么对象需要传的。。
msg.what = SUCCESS; //如果前面的操纵成功,失败的话就返回errsor
handle.sendMessage(msg);
}
});
th_current.start();
}
这种方式是我用的比较多的一种方式。。不过这个方法有个问题就是每次我们都会去开个线程。。。无疑增加了代码量。。同事利用java的反射机制写了一个小型的框架解决了这个问题。。代码量还是挺大的,有需要的话,二天再发吧。(这还有一个问题,就是线程执行完了后,怎么去回收它)
(二)使用Handler的post、postDelayed方法。
public void testHandler(){
r = new Runnable() {
@Override
public void run() {
// TODO Auto-generated method stub
Toast.makeText(context, "ssssssss",Toast.LENGTH_SHORT).show();
txt_infos.setText("sf");
}
};
handle.postDelayed(r, 1000); //延迟1秒执行
}
发现问题没?我居然可以在runnalbe里面直接去更新UI了。这里就是Looper出了问题。因为主线程(UI)已经封装了自己的Looper对象(系统源码就不贴了),导致我们在这里开的话,代码还是在UI线程里执行的,一样会堵塞UI线程,所以handler.postDelayed我们一般用于去主动中断UI线程一会,比如说做个开启应用的动画什么的。。个人推荐费时操作使用第一种方法。
(三)我们做网络请求等费时操作时,可以使用AsyncTask去操作,个人感觉,由于AsyncTask封装的比较好,使用起来还是比较简单的。其实看过AsyncTask源码的人都知道,其实它里面建立了一个ThreadPool,也是使用的handler去更新UI的。
Looper和Message和MessageQueue下次再说吧。。(未完待续)