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决定。

猜你喜欢

转载自blog.csdn.net/m18180201066/article/details/89336802