Handler、Loop和MessageQueue

一、Android之线程信使

曾在网上看到一个段子。

面试时,面试官问码农:xxx是线程安全的吗?

码农果断答道:是线程安全的。

面试官:(⊙o⊙)…我正准备接着问为什么不是线程安全的

……

然后就没有然后了。

那么,同样的问题:Android的UI操作是线程安全的吗?

(不要回答的太果断啊)

答案肯定是:不是线程安全的。具体吗?我想这个链接已经说的基本清楚了:http://chenjinhua1595515.blog.163.com/blog/static/21583214720140834012400/

回归正题,Android中有一条规则:只允许UI线程修改Activity里的UI组件,而如果需要在新线程中更新UI线程的组件,则需要通过一个信使:Handler。

Handler类主要有两个作用:

(1)在新线程中发送消息。

(2)在UI线程中获取、处理消息。

好,so easy!完活儿。

二、Handler、Loop和MessageQueue组件

真的这么简单吗?新启动的线程何时发送消息?UI线程何时获取消息?以及消息的传递机制呢?这就有必要了解一下和Handler一起工作的小伙伴啦。

Message:消息(直译,哈哈)。Handler接收和处理的就是它。

Looper:(这个不太好直译)刚开始学的时候,一上来就是东西最难理解,后来发现这个东西就是连接MessageQueue和Handler的中间人,负责把MessageQueue中的Message取出来,送给Handler去处理。需要注意的是:每个线程只有一个Looper。

MessageQueue:消息队列。大家肯定都知道队列的实现机制,不知道也没事,一句话,先进先出。

在线程中使用Handler的步骤有以下三步:

(1)通过Looper的prepare()方法为当前线程创建Looper对象

private Looper() {
     mQueue = new MessageQueue();
     mRun = true;
     mThread = Thread.currentThread();
}
可见,同时创建了与之配套的MessageQueue。

(2)创建Handler子类的实例,重写handleMessage()方法,该方法负责处理其他线程的消息。

Handler mHandler = new Hander() {
     @Override
     public void handleMessage(Message msg) {
     if(msg.what == VALUE)
     // WHAT YOU WANT TO DO 
}
}
(3)调用Looper的loop方法来启动Looper。loop方法是一个静态方法,网上有它的源代码,是一个死循环不断的取出MessageQueue中的消息,并将其分给该消息对应的Handler处理。代码较长,这里不再贴出。

三、网络编程时的多线程

在Android端的网络编程时(关于网络编程,后续博客中会具体阐述),多线程是必须的编程方法,比如:与服务器进行通信的代码需要在新线程中完成,响应用户操作的代码需要在UI线程中完成……(当然,根据需求,可能这里有非常多的线程,比如多线程下载),这里,仅举例说明网络连接的线程和主线程。

以最简单的登陆服务器为例:

loginButton.setOnClickListener(new OnClickListener() {

			@Override
			public void onClick(View arg0) {
				final String name = ((EditText) findViewById(R.id.log_in_name_input)).getText().toString();
				final String password = ((EditText) findViewById(R.id.log_in_password_input)).getText().toString();
				new Thread() {
					@Override
					public void run() {
						try {
							HttpPost post = new HttpPost("http://xxx.xxx.xx.xxx:8080/APPLICATION_NAME/login.jsp");
							List<NameValuePair> params = new ArrayList<NameValuePair>();
							params.add(new BasicNameValuePair("name", name));
							params.add(new BasicNameValuePair("pass", password));								
							post.setEntity(new UrlEncodedFormEntity(params, HTTP.UTF_8));
							HttpResponse response = httpClient.execute(post);
							if (response.getStatusLine().getStatusCode() == 200) {
								String msg = EntityUtils.toString(response.getEntity());
								<strong>Looper.prepare();
							Toast.makeText(MainActivity.this, msg, Toast.LENGTH_SHORT).show();
							Looper.loop();</strong>
							}
						}
						catch (Exception e) {
							e.printStackTrace();
						}
					}
				}.start();
			}
		});
	}
在监听登陆按钮时,需要新启动一个线程,进行与服务器的连接,在监听到服务器成功返回响应之后,首先,通过response.getEntity()方法取得返回的内容,然后通过prepare()方法创建Looper对象,最后调用loop()方法启动Looper。


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值