转载请注明原文地址: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学习笔记十:异步处理的更多相关文章

  1. android学习笔记十——TabHost

    TabHost——标签页 ==> TabHost,可以在窗口放置多个标签页,每个标签页相当于获得了一个与外部容器相同大小的组件摆放区域. 通过此种方式可以实现在一个容器放置更多组件(EG:通话记 ...

  2. 【转】Pro Android学习笔记(三十):Menu(1):了解Menu

    目录(?)[-] 创建Menu MenuItem的属性itemId MenuItem的属性groupId MenuItem的属性orderId MenuItem的属性可选属性 Menu触发 onOpt ...

  3. 【转】 Pro Android学习笔记(二十):用户界面和控制(8):GridView和Spinner

    目录(?)[-] GridView Spinner GridView GridView是网格状布局,如图所示.在了解ListView后,很容易了解GridView.下面是例子的XML文件. <? ...

  4. 【转】 Pro Android学习笔记(十九):用户界面和控制(7):ListView

    目录(?)[-] 点击List的item触发 添加其他控件以及获取item数据 ListView控件以垂直布局方式显示子view.系统的android.app.ListActivity已经实现了一个只 ...

  5. 【转】 Pro Android学习笔记(七十):HTTP服务(4):SOAP/JSON/XML、异常

    目录(?)[-] SOAP JSON和XMLPullParser Exception处理 文章转载只能用于非商业性质,且不能带有虚拟货币.积分.注册等附加条件,转载须注明出处:http://blog. ...

  6. 【转】 Pro Android学习笔记(四十):Fragment(5):适应不同屏幕或排版

    目录(?)[-] 设置横排和竖排的不同排版风格 改写代码 对于fragment,经常涉及不同屏幕尺寸和不同的排版风格.我们在基础小例子上做一下改动,在横排的时候,仍是现实左右两个fragment,在竖 ...

  7. 【转】Pro Android学习笔记(十四):用户界面和控制(2):Text类控制

    目录(?)[-] TextView 例子1在XML中设置autoLink属性 例子2在代码中设置autoLink属性 EditText AutoCompleteTextView MultiAutoCo ...

  8. 【转】Pro Android学习笔记(十二):了解Intent(下)

    解析Intent,寻找匹配Activity 如果给出component名字(包名.类名)是explicit intent,否则是implicit intent.对于explicit intent,关键 ...

  9. 【转】Pro Android学习笔记(十):了解Intent(上)

    目录(?)[-] Intent基本含义 系统的Intent Android引入了Intent的概念来唤起components,component包括:1.Activity(UI元件) 2.Servic ...

随机推荐

  1. Process 'command '/Users/lidaqiang/Library/Android/sdk/build-tools/27.0.3/aapt'' finished with non-zero exit value 1

    Process 'command '/Users/lidaqiang/Library/Android/sdk/build-tools/27.0.3/aapt'' finished with non-z ...

  2. CSS3 Flex布局整理(二)-容器属性

    一.Flex容器属性介绍 1.flex-flow :水平或垂直方向上的流动方式,包裹处理,其中包括了flex-direction属性和flex-wrap属性. 2.justify-content:定义 ...

  3. Django静态文件的加载以及STATIC_URL、 STATIC_ROOT 、STATICFILES_DIRS的区别

    Djangon生产环境静态资源的处理 Django 关闭DEBUG模式后,就相当于是生产环境了. Django框架一旦作为生产环境,它的静态文件访问接口就不应该从Django框架中走,必须在Djang ...

  4. Chapter 6 -- Caches

    CachesExplained Explanation for how to use Guava caches. explained Updated Jun 4, 2013 by lowas...@g ...

  5. B. Random Teams(Codeforces Round 273)

    B. Random Teams time limit per test 1 second memory limit per test 256 megabytes input standard inpu ...

  6. JavaScript:Number 对象

    ylbtech-JavaScript:Number 对象 1. Number 对象返回顶部 Number 对象 Number 对象是原始数值的包装对象. 创建 Number 对象的语法: var my ...

  7. QT国际化(中英转换)

    转载:https://blog.csdn.net/u012528526/article/details/54707233 QT国际化(中英转换) 我们都知道在安卓中,想做国际化很简单,只需要建立对应的 ...

  8. go语音之进阶篇爬百度贴吧单线程版本

    一.爬什么? 1.明确目标 : 知道你准备在那个范围或者网站去搜索 2.爬: 将所有的网站的内容全部爬下来 3.取:去掉对我们没用处的数据 4.处理数据:按照我们想要的方式存储或使用 二.百度贴吧小爬 ...

  9. 重启Windows的PowerShell

    这么简单的一个命令都单独写一篇blog, 是不是太无耻了? 好吧, 谁让咱不会呢. 学会了就来一篇. 呵呵. Restart-Computer   来源 ================ http:/ ...

  10. ORM数据库框架 SQLite ORMLite MD

    Markdown版本笔记 我的GitHub首页 我的博客 我的微信 我的邮箱 MyAndroidBlogs baiqiantao baiqiantao bqt20094 baiqiantao@sina ...