最近完成了一个多媒体播放器,更新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下次再说吧。。(未完待续)