Android线程通信机制(二)

Android线程通信机制(二)

在上一节中我们提到了MessageQueue和Looper,那么这一节中我们就说说这两个东东吧!

一般在大家默认的情况下,handler时在主线程中处理消息,即可以更新UI

一般正常我们的代码是handler时在主线程中创建

private Handler handler;

@Override
protected void onCreate(Bundle savedInstanceState) {
	super.onCreate(savedInstanceState);
	setContentView(R.layout.activity_main);

	handler = new Handler(new InnerHandlerCallback());
	sendMessage();

}


private class InnerHandlerCallback implements Handler.Callback {

	@Override
	public boolean handleMessage(Message msg) {
	
		return false;
	}
		
}


private void sendMessage(){

	new Thread() {
		public void run() {
			
			handler.sendEmptyMessage(0);
			
		}
	}.start();
}

这里我们将提到handler在子线程中创建

private Handler handler;

@Override
protected void onCreate(Bundle savedInstanceState) {
	super.onCreate(savedInstanceState);
	setContentView(R.layout.activity_main);

	new Thread() {
		public void run() {
			handler = new Handler(new InnerHandlerCallback());
			}
	}.start();

	sendMessage();

}


private class InnerHandlerCallback implements Handler.Callback {

	@Override
	public boolean handleMessage(Message msg) {
	
		return false;
	}
		
}


private void sendMessage(){

	new Thread() {
		public void run() {
			
			handler.sendEmptyMessage(0);
			
		}
	}.start();
}

但是程序在这里会报错,提示在没有Looper.prepare()情况下子线程中不能创建handler

所以我们为了解决错误就根据错误提示进行操作

private Handler handler;

@Override
protected void onCreate(Bundle savedInstanceState) {
	super.onCreate(savedInstanceState);
	setContentView(R.layout.activity_main);

	new Thread() {
		public void run() {
			// 解决错误:在子线程中创建Handler之前,必须调用Looper.prepare()
			Looper.prepare();
			handler = new Handler(new InnerHandlerCallback());
			Looper.loop();
			}
	}.start();

	sendMessage();

}


private class InnerHandlerCallback implements Handler.Callback {

	@Override
	public boolean handleMessage(Message msg) {
	
		return false;
	}
		
}


private void sendMessage(){

	new Thread() {
		public void run() {
			
			handler.sendEmptyMessage(0);
			
		}
	}.start();
}

所以我们在子线程中不可以直接创建handler,而是要先调用Looper.perpare()方法,并且还要调用Looper的loop()方法去轮询消息队列,取出消息交给handler处理。但是在这里会又有疑问,为什么主线程不调用perpare()和loop()方法,然而handler也能正常的接收消息呢?其实这里主线程已经存在调用了prepare()和loop()方法的Looper,所以主线程中创建handler的时候就不需要考虑Looper的问题了。

这里还需要注意的一个问题不是handler在哪个线程创建出来的就在哪个线程处理消息。而是Handler在哪个线程处理消息,取决于该Handler对象关联到的哪个线程的Looper对象。也就是说,如果子线程创建的Handler,关联到的是主线程的Looper对象,该Handler会在主线程处理消息。

获取looper

@Override
protected void onCreate(Bundle savedInstanceState) {
	super.onCreate(savedInstanceState);
	setContentView(R.layout.activity_main);

	new Thread() {
		public void run() {
			// 解决错误:在子线程中创建Handler之前,必须调用Looper.prepare()
			Looper.prepare();

			情况1 获取当前线程的Looper
			handler = new Handler(Looper.myLooper(),new InnerHandlerCallback());

			情况2 获取主线程线的Looper
			handler = new Handler(Looper.getMainLooper(),new InnerHandlerCallback());

			// 使Looper轮询
			Looper.loop();
			}
	}.start();

	sendMessage();

}

Handler被重载多次,所以在创建的时候我们可指定Looper,也可不指定Looper。如果在没有显式指定Looper对象的时候,那么系统会默认创建Handler对象的线程Looper,也就是说:在哪个线程创建Handler,就在哪个线程处理消息。指定的话就由指定的Looper决定。

 

 

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值