这篇文章是通过阅读“第一行代码”这个书,学习总结的,整理出自己的想法和借鉴作者的思想来充分理解:Android中的异步消息处理机制。

众所周知,Android的UI也是线程不安全的。也就是说,如果想要更新应用程序里的UI元素,则必须在主线程中进行,否则就会出现异常。

我们举一个形象的例子来说明这个问题:

功能实现:当我们点击Button按钮时,用于改变TextView中显示的内容。

activity_main.xml

    
MainActivity.java

package com.xbmu.handler;import android.app.Activity;import android.os.Bundle;import android.view.View;import android.view.View.OnClickListener;import android.widget.Button;import android.widget.TextView;public class MainActivity extends Activity implements OnClickListener {private Button button;private TextView textView;@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);button = (Button) findViewById(R.id.btn);textView = (TextView) findViewById(R.id.text);button.setOnClickListener(this);}@Overridepublic void onClick(View v) {switch (v.getId()) {case R.id.btn:new Thread(new Runnable() {@Overridepublic void run() {textView.setText("我是一匹黑马");}}).start();break;}}}
以上程序,我们可以看到在button按钮中我们设置了点击事件,在点击事件里面开启了一个子线程,然后在子线程中调用TextView的setText()方法将显示的字符串改为“我是一匹黑马”。说白了就是在子线程中更新了UI组件。

运行程序:

会发现程序直接崩溃了。并且查看log cat日志,发现报错信息:

android.view.ViewRootImpl$CalledFromWrongThreadException: Only the original thread that created a view hierarchy can touch its views.

大概意思就是:只能在原生线程(也就是主线程)中创建一个视图或者触摸(更改)这个视图


由此可见,以上的例子充分证明了:Android确实是不允许在子线程中进行UI操作的。但是有时候,我们在Android项目开发过程中,有时候需要进行一些耗时的操作(比如:通过联网,请求网络服务,从后台获取一些数据),然后将获取到的数据用来更新相应的UI控件,这该怎么办啊?

对于这种问题, google工程师,在Android底层提供了一套异步消息处理机制,完美的解决了在子线程中进行UI的操作。

修改MainActivity.java

package com.xbmu.handler;import android.app.Activity;import android.os.Bundle;import android.os.Handler;import android.os.Message;import android.view.View;import android.view.View.OnClickListener;import android.widget.Button;import android.widget.TextView;public class MainActivity extends Activity implements OnClickListener {protected static final int UPDATE_TEXT = 1;private Button button;private TextView textView;//创建handler对象,并重写父类handleMessage方法private Handler handler = new Handler(){//处理传递过来的消息public void handleMessage(android.os.Message msg) {switch (msg.what) {case UPDATE_TEXT://在这里更新UI操作textView.setText("我是一匹黑马");break;}};};@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);button = (Button) findViewById(R.id.btn);textView = (TextView) findViewById(R.id.text);button.setOnClickListener(this);}@Overridepublic void onClick(View v) {switch (v.getId()) {case R.id.btn:new Thread(new Runnable() {@Overridepublic void run() {Message message = new Message();message.what = UPDATE_TEXT;handler.sendMessage(message);//将message对象发送出去}}).start();break;}}}

运行成功:



这里只是简单的总结了一下我们在项目开发过程中经常遇到的问题及其解决方法,学会使用“异步消息处理机制”来在子线程中进行UI操作。

但是,我们不能仅满足于这些,学习一门技术,必须学会总结,归纳,深究其原理,我们才能掌握这门技术并能在适应的场景最后那个应用。

这里我们来介绍下“异步消息处理机制”,有什么不妥之处,请各位大神提出宝贵意见,毕竟我只是一个菜鸟,这是记录下自己学习的笔记,

希望能得到大家的指教与认可。

Android中的异步消息处理主要有四个部分组成:Message,Handler,MessageQueue,Looper。

Message:顾名思义,是消息的意思,主要作用在线程之间传递的消息,充当媒介作用,它可以在其内部携带少量的信息,

用于在不同线程之间交换数据,,比如:上面那个例子中就是通过Message对象携带数据在子线程和主线程之间传递消息。

Handler:顾名思义也就是处理者的意思,你想,我们通过Message将数据携带过来,肯定要将该数据进行处理,如果不打算处理,那我们

传递过来干什么啊。 handler主要用于发送和处理消息。发送消息一般是使用Handler的sendMessage()方法,而发出的消息经过一系列

的处理后,最终会传递到handler的handlerMessage()方法中。

MessageQueue:是消息队列的意思。它主要用于存放所有通过handler发送的消息。这部分消息会一直存在于消息队列中,等待被处理。每个线程中

只会右一个MessageQueue对象

Looper:是每个线程中的MessageQueue的管家,通过Looper的loop()方法后,就会进入到一个无限循环当中,然后每当发现MessageQueue中存在一个消息,

就会将它取出,并传递到Handler的handlerMessage()方法中。每个线程只有一个Looper对象。


我们整理梳理一下异步消息处理机制运行的流程:

首先需要在主线程当中创建一个Handler对象,并重写handleMessage()方法。然后当子线程中需要进行UI操作的时,就创建一个Message对象,并通过

Handler将这条消息发送出去。之后这条消息会被添加到MessageQueue的队列中等待被处理,而Looper则会一直尝试从MesssageQueue中取出待处理消息,

最后发回Handler的HandleMessage()方法中。

由于Handler是在主线程中创建的,所以此时handleMessage()方法中的代码页会在主线程中运行,于是我们在这里就可以进行UI操作了。




更多相关文章

  1. 详解Android使用OKHttp3实现下载(断点续传、显示进度)
  2. Android(安卓)绑定类型服务---简介
  3. Android引入外部自定义特殊字体的方法
  4. android开发之Android(安卓)Interface Definition Language(AIDL)
  5. Android解决自定义View获取不到焦点的情况
  6. Android(安卓)Studio——Android(安卓)View 如何绘制
  7. (转)Android中Dialog的“生命周期”
  8. Android文件下载之进度检测
  9. Android消息处理机制——Looper、Handler、Message 源码分析

随机推荐

  1. Android(安卓)init源代码分析(1)概要分析
  2. 打造android ORM框架opendroid(六)——级
  3. Android内核开发:学会分析系统的启动log
  4. 解开Android应用程序组件Activity的"sing
  5. 信息浏览器从Android的浏览器中传递cooki
  6. 转载:Android(安卓)解压zip文件
  7. 基于Xmpp,Openfire和Asmack的聊天软件的开
  8. Android自定义字体样式Typeface的三种技
  9. [转]自己整理的android入门QA表,希望能帮
  10. Android系统的架构