ohdajing 2011-07-01
本文章主要讲解下AsyncTask的使用。
首先,我们得明确下一个概念,什么是UI线程。顾名思义,ui线程就是管理着用户界面的那个线程!
android的ui线程操作并不是安全的,并且和用户直接进行界面交互的操作都必须在ui线程中进行才可以。这种模式叫做单线程模式。我们在单线程模式下编程一定要注意:不要阻塞ui线程、确保只在ui线程中访问ui组件。
当我们要执行一个复杂耗时的算法并且最终要将计算结果反映到ui上时,我们会发现,我们根本没办法同时保证上面的两点要求;我们肯定会想到开启一个新的线程,让这个复杂耗时的任务到后台去执行,但是执行完毕了呢?我们发现,我们无法再与ui进行交互了。
为了解决这种情况,android为我们提供了很多办法。
1)、handler和message机制:通过显示的抛出、捕获信息与ui进行交互;
2)、Activity.runOnUiThread(Runnable):如果当前线程为ui线程,则立即执行;否则,将参数中的线程操作放入到ui线程的事件队列中,等待执行。
3)、View.post(Runnable):将操作放入到message队列中,如果放入成功,该操作将会在ui线程中执行,并返回true,否则返回false
4)、View.postDelayed(Runnable,long)跟第三条基本一样,只不过添加了一个延迟时间。
5)、android1.5以后为我们提供了一个工具类来搞定这个问题AsyncTask.
AsyncTask是抽象类.AsyncTask定义了三种泛型类型Params,Progress和Result。
Params启动任务执行的输入参数,比如HTTP请求的URL
。
Progress后台任务执行的百分比。
Result后台执行任务最终返回的结果,比如String
。
用程序调用,开发者需要做的就是实现这些方法。
1)子类化AsyncTask
2)实现AsyncTask中定义的下面一个或几个方法
onPreExecute(),该方法将在执行实际的后台操作前被UIthread调用。可以在该方法中做一些准备工作,如在界面上显示一个进度条。
doInBackground(Params...),将在onPreExecute方法执行后马上执行,该方法运行在后台线程中。这里将主要负责执行那些很耗时的后台计算工作。可以调用publishProgress方法来更新实时的任务进度。该方法是抽象方法,子类必须实现。
onProgressUpdate(Progress...),在publishProgress方法被调用后,UIthread将调用这个方法从而在界面上展示任务的进展情况,例如通过一个进度条进行展示。
onPostExecute(Result),在doInBackground执行完成后,onPostExecute方法将被UIthread调用,后台的计算结果将通过该方法传递到UIthread.
为了正确的使用AsyncTask类,以下是几条必须遵守的准则:
1)Task的实例必须在UIthread中创建
2)execute方法必须在UIthread中调用
3)不要手动的调用onPreExecute(),onPostExecute(Result),doInBackground(Params...),onProgressUpdate(Progress...)这几个方法
4)该task只能被执行一次,否则多次调用时将会出现异常
viewplaincopytoclipboardprint?
01.packagecn.com.chenzheng_java;
02.
03.importandroid.os.AsyncTask;
04./**
05.*
06.*@authorchenzheng_java
07.*@description异步任务AcyncTask示例
08.*
09.*/
10.publicclassMyAsyncTaskextendsAsyncTask<String,Integer,Object>{
11.
12./**
13.*该方法由ui线程进行调用,用户可以在这里尽情的访问ui组件。
14.*很多时候,我们会在这里显示一个进度条啥的,以示后台正在
15.*执行某项功能。
16.*/
17.@Override
18.protectedvoidonPreExecute(){
19.super.onPreExecute();
20.}
21.
22./**
23.*该方法由后台进程进行调用,进行主要的耗时的那些计算。
24.*该方法在onPreExecute方法之后进行调用。当然在执行过程中
25.*我们可以每隔多少秒就调用一次publishProgress方法,更新
26.*进度信息
27.*/
28.@Override
29.protectedObjectdoInBackground(String...params){
30.returnnull;
31.}
32.
33.
34./**
35.*doInBackground中调用了publishProgress之后,ui线程就会
36.*调用该方法。你可以在这里动态的改变进度条的进度,让用户知道
37.*当前的进度。
38.*/
39.@Override
40.protectedvoidonProgressUpdate(Integer...values){
41.super.onProgressUpdate(values);
42.}
43.
44./**
45.*当doInBackground执行完毕之后,由ui线程调用。可以在这里
46.*返回我们计算的最终结果给用户。
47.*/
48.@Override
49.protectedvoidonPostExecute(Objectresult){
50.super.onPostExecute(result);
51.}
52.
53.
54.
55.
56.}
packagecn.com.chenzheng_java;
importandroid.os.AsyncTask;
/**
*
*@authorchenzheng_java
*@description异步任务AcyncTask示例
*
*/
publicclassMyAsyncTaskextendsAsyncTask<String,Integer,Object>{
/**
*该方法由ui线程进行调用,用户可以在这里尽情的访问ui组件。
*很多时候,我们会在这里显示一个进度条啥的,以示后台正在
*执行某项功能。
*/
@Override
protectedvoidonPreExecute(){
super.onPreExecute();
}
/**
*该方法由后台进程进行调用,进行主要的耗时的那些计算。
*该方法在onPreExecute方法之后进行调用。当然在执行过程中
*我们可以每隔多少秒就调用一次publishProgress方法,更新
*进度信息
*/
@Override
protectedObjectdoInBackground(String...params){
returnnull;
}
/**
*doInBackground中调用了publishProgress之后,ui线程就会
*调用该方法。你可以在这里动态的改变进度条的进度,让用户知道
*当前的进度。
*/
@Override
protectedvoidonProgressUpdate(Integer...values){
super.onProgressUpdate(values);
}
/**
*当doInBackground执行完毕之后,由ui线程调用。可以在这里
*返回我们计算的最终结果给用户。
*/
@Override
protectedvoidonPostExecute(Objectresult){
super.onPostExecute(result);
}
}
------------------------------------------------------------------------------------------
AsyncTask的执行分为四个步骤,每一步都对应一个回调方法,这些方法不应该由应