Handler消息机制

一、Handler概述

在安卓中,主线程如果执行一段耗时较长的代码(5-10秒),在这个耗时较长的操作未执行完毕之前,会暂停刷新界面和暂停处理用户操作请求,这时如果用户发出操作请求,就会出现ANR异常(application not response

执行下面一段代码,程序会出现异常

<span style="font-size:14px;">public class SendMessageActivity extends Activity {

	private TextView numberTV;
	

	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.activity_main);	// 主线程解析XML, 创建对象, 设置Activity的界面
		numberTV = (TextView) findViewById(R.id.numberTV);
	}

	public void onClick(View v) throws Exception {
		new Thread(){
			public void run() {
				try {
					for (int i = 0;; i++) {	// 主线程(UI Thread)如果执行一段代码, 那么就会暂停刷新界面和暂停处理用户操作
						System.out.println(i);	// 后台打印
						numberTV.setText(i+"");
						Thread.sleep(1000);
					}
				} catch (InterruptedException e) {
					e.printStackTrace();
				}
			}
		}.start();
	}
}</span>
android.view.ViewRootImpl$CalledFromWrongThreadException: Only the original thread that created a view hierarchy can touch its views.  这段异常的意思就是只有创建了view对象的线程也就是主线程才能修改这个view,也就是说对界面的修改只能在主线程进行。

碰到这种做耗时操作的时候需要开启新线程, 新线程又需要更新界面, 这时就需要新线程通过Handler和主线程通信。

在实际的应用中,我们会碰到很多耗时的操作,比如读取网络资源,读取数据库,读取联系人等等,这种时候,我们就可以通过使用handler来将新线程和主线程进行通信,来达到及时更新界面的目的。

Handler有两个重要的方法:sendMessage方法和post方法,下面来分别介绍一下这两个方法。


二、sendMessage方法

先在主线程创建一个Handler对象
新线程使用Handler.sendMessage()方法, 可以从新线程向主线程发送一个Message对象(其中可以包含数据)
主线程就会自动执行Handler.handleMessage()方法, 得到Message对象

将上面的程序稍加修改,使用Handler来进行线程之间的通信。

<span style="font-size:14px;">public class SendMessageActivity extends Activity {

	private TextView numberTV;
	private Handler handler = new Handler(){
		public void handleMessage(Message msg) {	// 主线程创建Handler对象的子类, 实现了handleMessage()方法
			int i = msg.getData().getInt("i");		// 得到Message对象, 获取Bundle, 获取i
			numberTV.setText(i + "");				// 主线程设置界面, 只有创建该对象的线程才能修改它
		}
	};		

	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.activity_main);			// 主线程解析XML, 创建对象, 设置Activity的界面
		numberTV = (TextView) findViewById(R.id.numberTV);
	}

	public void onClick(View v) throws Exception {
		new Thread(){
			public void run() {
				try {
					for (int i = 0;; i++) {	// 主线程(UI Thread)如果执行一段代码, 那么就会暂停刷新界面和暂停处理用户操作
						System.out.println(i);	// 后台打印
						Message msg = new Message();
						msg.getData().putInt("i", i);// 获取Message中的Bundle(Map), 装入数据
						handler.sendMessage(msg);// 新线程使用Handler发送Message, 主线程会自动执行handleMessage()方法
						Thread.sleep(1000);
					}
				} catch (InterruptedException e) {
					e.printStackTrace();
				}
			}
		}.start();
	}
}</span>

如果要修改多个页面,可以用Message类的一个what方法 msg.what 定义不同的常量值赋给不同的msg.what   通过handler对象的sendMessage方法将msg消息发到主线程中去,然后在主线程handler的 handleMessage方法中对接收到的msg作处理,使用msg.what 对不同的值进行响应的操作,就可以完成多个页面的修改。



三、post方法

先在主线程创建一个Handler对象  这时,不需创建子类重写handleMessage方法
新线程使用Handler.post()方法发送一个Runnable对象, 主线程会自动执行Runnable的run()

public class PostActivity extends Activity {

	private TextView numberTV;
	private Handler handler = new Handler();		
	private int i;

	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.activity_main);			// 主线程解析XML, 创建对象, 设置Activity的界面
		numberTV = (TextView) findViewById(R.id.numberTV);
	}

	public void onClick(View v) throws Exception {
		new Thread(){
			public void run() {
				try {
					for (i = 0;; i+=2) {		// 主线程(UI Thread)如果执行一段代码, 那么就会暂停刷新界面和暂停处理用户操作
						System.out.println(i);	     // 后台打印
						handler.post(new Runnable(){	// 新线程使用post()发送一个Runnable给主线程, 主线程自动执行run()
							public void run() {
								numberTV.setText(i + "");
							}
						});
						Thread.sleep(1000);
					}
				} catch (InterruptedException e) {
					e.printStackTrace();
				}
			}
		}.start();
	}
}





 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

douban.com/note/361619484/
douban.com/note/361619497/
douban.com/note/361619520/
douban.com/note/361619547/
douban.com/note/361619560/
douban.com/note/361619599/
douban.com/note/361619639/
douban.com/note/361619679/
douban.com/note/361619714/
douban.com/note/361619785/
douban.com/note/361619793/
douban.com/note/361619803/
douban.com/note/361619841/
douban.com/note/361619910/
douban.com/note/361619940/
douban.com/note/361619975/
douban.com/note/361620031/
douban.com/note/361620050/
douban.com/note/361620111/
douban.com/note/361620145/
douban.com/note/361620156/
douban.com/note/361620163/
douban.com/note/361620192/
douban.com/note/361620226/
douban.com/note/361618877/
douban.com/note/361619458/
douban.com/note/361619465/
douban.com/note/361619511/
douban.com/note/361619531/
douban.com/note/361619554/
douban.com/note/361619574/
douban.com/note/361619616/
douban.com/note/361619659/
douban.com/note/361619694/
douban.com/note/361619739/
douban.com/note/361619760/
douban.com/note/361619823/
douban.com/note/361619863/
douban.com/note/361619907/
douban.com/note/361619952/
douban.com/note/361619997/
douban.com/note/361620049/
douban.com/note/361620064/
douban.com/note/361620075/
douban.com/note/361620088/
douban.com/note/361620188/
douban.com/note/361620216/
douban.com/note/361620256/
douban.com/note/361620274/
douban.com/note/361620308/
douban.com/note/361620342/

 

 

 



 


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值