Android handler 学习整理

为什么要用Handler

在java中我们常用多线程来处理问题,android也会遇到一些耗时长的操作,比如查询数据库,根据查询的结果更新UI,如果放在主线程中就会导致等待时间很长,用户的体验会很差。
android实现子线程的方法和java中一样,新建类继承Thread,新建类实现Runnable接口,或者内部类实现该接口,最常用的就是第三种
这里插入一个代码片

public void onClick(View v){
	switch(v.getId()){
		case R.id.button:
		new Thread(new Runnable(){
			@Override
			public void run(){
				text.setText("hello world!");
			}	
		});
	}
}

这就是在子线程中更新ui,如果运行就会抛出异常,因为android不允许在子线程中更新ui,那么要根据子线程的结果更新Ui,我们就需要用到android中的异步消息处理机制:handler

handler可以大致分为四个部分
1.message:被传递的对象,为了分清是谁传递的,它带有what字段作为标记
2.handler 用于发送和处理消息,发送消息会调用sendMessage()方法,处理消息会用到handleMessage()方法。
3.MessageQueue消息队列,存放message,每个线程只会有一个MessageQueue对象。
4.Looper 相当于消息队列的管家,调用Looper的loop()方法后,就会进入到无限循环中,每当消息队列中存入一条消息就会将它取出,传递给handleMessage,每个线程只会有一个Looper对象。

那么最后整理一下如何实现根据子线程的结果更新UI:
首先新建Handle对象,重新handleMessage方法,在子线程需要更新UI时,就新建一个message对象,调用sendMessage将数据发送给主线程,更新UI

子线程
public void onClick(View v){
	switch(v.getId()){
		case R.id.button:
		new Thread(new Runnable(){
			@Override
			public void run(){
				Message message=new Message();
				message.what=1;
				handler.sendMessage(message);
			}	
		});
	}
}
主线程
private Handler handler =new Handler(){
	public void handleMessage(Message msg){
		switch(msg.what){
			case 1:
				//更新UI
				break;
			default:
				break;
		}
	}
}
handler也常用于循环发送查询

举个例子,视频的播放进度时长显示,textview需要隔一段时间查询播放器,更新文本内容显示当前播放的时间。这时候就可以在handmessage中调用handler.sendmessageDelay每隔多少秒发送消息给自身达到循环的目的

handler发送消息的方法

分为两个大类,send和post,调用send就是发送message对象,post就是发送Runnable对象(内部类实现),这里post的Runnable对象是UI线程,并不会创建真正的子线程,注意handler定义要在主线程中定义,因为handler默认是使用定义所在线程的looper,所以如果在子线程中定义无参数的handler就会报错:RuntimeException: Can’t create handler inside thread that has not called Looper.prepare()

消息的优先级

messageQueue内部的单元肯定是有序的,根据优先级的高低进行排序,这个优先级就是message#when,Message#when 是一个时间,用于表示 Message 期望被分发的时间,该值是 SystemClock#uptimeMillis() 与 delayMillis 之和。

子线程创建handler

之前又提过无法在子线程中直接创建无参数的handler如果业务需求在主线程中发消息给子线程让它进行,那么就需要在子线程中创建handler,如果无参数构造就会自动传入当前线程的looper,但android只会自动创建主线程的looper,所以就会报上面的错误,因为在子线程中并没有启动相应的looper,如果想在子线程中使用handler就需要调用looper.prepare创建looper,然后拿到实例或者调用Looper.myLooper获取当前线程的looper实例,最后调用looper.loop启动循环。注意Looper.loop()这个方法是无限循环的,所以在Looper.loop()后边的程序代码块是无法执行到的,如果传入的是getMainLooper,实际上执行的还是在主线程中,就是一个线程绑定一个looper。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值