Android学习笔记十:异步处理
转载请注明原文地址:http://www.cnblogs.com/ygj0930/p/7520700.html
一:基础概念
UI线程:当Android程序第一次启动时,Android会同时启动一条主线程(Main Thread),主线程主要负责处理与UI相关的事件,如用户的按键事件、屏幕绘图事件,并把相关的事件分发到对应的组件进行处理。主线程通常又被称为UI线程,Android只允许UI线程修改Activity里的UI组件。
子线程:在程序的activity中创建、启动的线程为子线程,子线程中不能操作UI组件。
后台任务:后台任务一般用子线程来完成,通常用于执行一些耗时任务如:复杂计算、下载文件等。因为这些操作是与UI线程同时运作的,所以又称为异步操作。
二:异步方式之——消息传递机制
我们知道,只有UI线程才能修改、操作界面组件,那么其他子线程中的信息如何反映到UI中呢?那就需要子线程把信息汇总到UI线程,由UI线程显示到组件上。
这个过程,就是消息传递机制。
1)消息传递机制原理图

2)消息传递机制解释
首先,UI线程中维护一个消息队列MessageQueue、一个循环者Looper、一个处理者Handler:消息队列负责接受、存储其他子线程发送过来的消息,等待UI线程处理;循环者不停地轮询消息队列,每次都提取队首一个消息;处理者负责处理Looper提取出来的消息,并负责把结果在UI进行呈现。其中,MessageQueue和Looper随着UI线程启动而自动创建并运行,Handler则需要手动定义。
其次,在UI线程中创建并启动子线程,子线程中通过同一个handler(通常这个handler为acticity代码中的全局变量,因此子线程中可见)来发送消息,从而把消息发送到了当前UI线程的handler对应的消息队列中。
3)实现步骤
根据消息传递机制的原理,我们只需针对实现各个环节需要的东西即可。
首先:定义、创建Handler,重写其中的handlerMessage方法,处理消息
private Handler mHandler = new Handler() {
@Override
public void handleMessage(Message msg) {
switch (msg.what) {
//根据消息内容,作处理
}
}
};
然后:定义子线程,在其中定义发送消息语句
Runnable runnable = new Runnable() {
@Override
public void run() {
Message message = new Message();
message.what = 消息标签;
mHandler.sendMessage(message); //handler是UI线程中的handler
}
};
最后:根据条件,创建子线程实例并启动
mThread = new Thread(runnable);
mThread.start();
4)应用场景
Handler机制适合多个子线程存在的情况,这样可以把多个子线程发送过来的信息在UI线程中统一处理、绘制呈现。
【附:如果需要在子线程中使用handler和looper,则需要获取到UI线程中的handler、looper对象。具体方法见:http://blog.csdn.net/logicteamleader/article/details/46591499】
三:单个异步任务——AsyncTask
消息传递机制看起来比较复杂,涉及到了消息队列的应用,这几乎是大型Web应用的架构层面才会用到的模式了。
如果只是单个的异步任务,用消息传递机制就有些过于麻烦了,为此,Android为我们提供了一个辅助类——AsyncTask。
AsyncTask类,可以理解为异步任务执行者;这个类的设计目的很明确,就是为了“执行一个较为耗时的异步任务(最多几秒钟),然后更新界面”。
1:使用AsyncTask
1)继承AsyncTask,定义子类,重写其中的几个方法:
AsyncTask需要重写5个方法,分别是:
1、onPreExecute方法:准备运行,该回调函数在任务被执行之后立即由UI线程调用,一般可以显示进度条。
2、doInBackground(Params ...)方法:正在后台运行,通常在这里执行耗时的后台计算,计算结果返回给函数,这里如果AsyncTask的第三个参数是Void的话不需要返回,这里不能更新UI,但是可以调用publishProgress(Progress ...)方法完成。
3、onProgressUpdate(Progress ...)方法:进度更新,UI线程在publishProgress(Progress ...)方法调用完成后被调用,一般动态显示一个进度。
4、onPostExecute(Result)方法:完成后台任务,会返回,这里可以进行些UI的操作,比如提醒任务执行的结果,以及关闭掉进度条对话框等。
5、onCancelled方法:取消任务,在调用AsyncTask的cancel()方法的时候调用。
class ViewContentTask extends AsyncTask<Void, Integer, Boolean> {//三个范型分别对应下面doInBackground、onProgressUpdate、onPostExecute三个方法的参数类型
@Override
protected Boolean doInBackground(Void... voids) {
return null;
}
@Override
protected void onProgressUpdate(Integer... values) {
}
@Override
protected void onPostExecute(Boolean b) {
//操作UI组件
}
@Override
protected void onPreExecute() {
}
@Override
protected void onCancelled() {
}
}
2)创建异步任务实例,启动异步任务
ViewContentTask task = new ViewContentTask();
task.execute();
2:AsyncTask工作原理
当一个异步任务被执行时,要经历四步:
onPreExecute(),在UI线程中执行,它会在异步任务开始前执行,一般用来设置任务参数;
doInBackground, 最重要的方法,在子线程中执行(事实上,只有它在子线程中执行,其他方法都在UI线程中执行)。当onPreExecute结束后,本方法立刻执行,它用 来进行后台的耗时计算,异步任务的参数会被传给它,执行完成的结果会被送给第四步;执行途中,它还可以调用publishProgress 方法来通知UI线程当前执行的进度;
onProgressUpdate, 当publishProgress 被调用后,它在UI线程中执行,刷新任务进度,一般用来刷新进度条等UI部件;
onPostExecute, 当后台的异步任务完成后,它会在UI线程中被调用,并获取异步任务执行完成的结果。
Android学习笔记十:异步处理的更多相关文章
- android学习笔记十——TabHost
TabHost——标签页 ==> TabHost,可以在窗口放置多个标签页,每个标签页相当于获得了一个与外部容器相同大小的组件摆放区域. 通过此种方式可以实现在一个容器放置更多组件(EG:通话记 ...
- 【转】Pro Android学习笔记(三十):Menu(1):了解Menu
目录(?)[-] 创建Menu MenuItem的属性itemId MenuItem的属性groupId MenuItem的属性orderId MenuItem的属性可选属性 Menu触发 onOpt ...
- 【转】 Pro Android学习笔记(二十):用户界面和控制(8):GridView和Spinner
目录(?)[-] GridView Spinner GridView GridView是网格状布局,如图所示.在了解ListView后,很容易了解GridView.下面是例子的XML文件. <? ...
- 【转】 Pro Android学习笔记(十九):用户界面和控制(7):ListView
目录(?)[-] 点击List的item触发 添加其他控件以及获取item数据 ListView控件以垂直布局方式显示子view.系统的android.app.ListActivity已经实现了一个只 ...
- 【转】 Pro Android学习笔记(七十):HTTP服务(4):SOAP/JSON/XML、异常
目录(?)[-] SOAP JSON和XMLPullParser Exception处理 文章转载只能用于非商业性质,且不能带有虚拟货币.积分.注册等附加条件,转载须注明出处:http://blog. ...
- 【转】 Pro Android学习笔记(四十):Fragment(5):适应不同屏幕或排版
目录(?)[-] 设置横排和竖排的不同排版风格 改写代码 对于fragment,经常涉及不同屏幕尺寸和不同的排版风格.我们在基础小例子上做一下改动,在横排的时候,仍是现实左右两个fragment,在竖 ...
- 【转】Pro Android学习笔记(十四):用户界面和控制(2):Text类控制
目录(?)[-] TextView 例子1在XML中设置autoLink属性 例子2在代码中设置autoLink属性 EditText AutoCompleteTextView MultiAutoCo ...
- 【转】Pro Android学习笔记(十二):了解Intent(下)
解析Intent,寻找匹配Activity 如果给出component名字(包名.类名)是explicit intent,否则是implicit intent.对于explicit intent,关键 ...
- 【转】Pro Android学习笔记(十):了解Intent(上)
目录(?)[-] Intent基本含义 系统的Intent Android引入了Intent的概念来唤起components,component包括:1.Activity(UI元件) 2.Servic ...
随机推荐
- 用UIBezierPath数组对UIView进行镂空处理
用UIBezierPath数组对UIView进行镂空处理 效果 源码 // // CutOutClearView.h // CutOutMaskView // // Created by YouXia ...
- UICollectionViewFlowLayout使用示例
UICollectionViewFlowLayout使用示例 效果 源码 https://github.com/YouXianMing/iOS-Project-Examples // // ViewC ...
- curl win
curl -H "tocken: 123456789" -H "userName: admin" http://39.18.10.2/log/v1/err ...
- Java中的Future模式原理自定义实现
摘要:Future模式类似于js中的ajax等,是一个异步获取数据的机制,这里我把自己的一些形象理解通过代码实现了一下.该机制可以形象的理解为:调用获取数据的方法,首先获得一个没有装数据的空箱子(这个 ...
- iOS:三种常见计时器(NSTimer、CADisplayLink、dispatch_source_t)的使用
一.介绍 在iOS中,计时器是比较常用的,用于统计累加数据或者倒计时等,例如手机号获取验证码.计时器大概有那么三种,分别是:NSTimer.CADisplayLink.dispatch_source_ ...
- c++流缓冲学习---rdbuf()
我们使用STL编程的时候有时候会想到把一个流对象指向的内容用另一个流对象来输出,比如想把一个文件的内容输出到显示器上,我们可以用简单的两行代码就可以完成: ifstream infile(" ...
- FreePascal - Typhon在Windows10 X64下的使用问题!
Typhon是CodeTyphon中的开发FreePascal的IDE工具. 在Windows10 X64中安装完CodeTyphon后,我们会发现有两套Typhon,分别对应32位和64位,32位可 ...
- Python collections.OrderedDict解决dict元素顺序问题
编程中遇到个问题,python json.loads时元素顺序可能会发生变化. 这个对于一些需要使用元素顺序来做一些策略的代码来说是致命的. 在网上查了查,结合自己的知识总结一下. 使用dict时,K ...
- GDB 程序调试简单实践
用了好久的GCC/G++ 却一直都没用过GDB调试过程序,有时程序不是非常大,一般有错,直接看编译器编译结果就几乎相同知道错在哪儿了,或者使用codeblocks单步调试,甚至回到windows以下调 ...
- mysql 字符串按照数字类型排序
一个varchar,char的字段 存放 1+,12- ,11等字符串将字段*1或者+0可以将MySQL字符串字段按数值排序 order by 字段名称+0 desc/asc的形式进行排序 order ...