AsyncTask介绍

Android的AsyncTask比Handler更轻量级一些,适用于简单的异步处理。

首先明确Android之所以有Handler和AsyncTask,都是为了不阻塞主线程(UI线程),且UI的更新只能在主线程中完成,因此异步处理是不可避免的。

Android为了降低这个开发难度,提供了AsyncTask。AsyncTask就是一个封装过的后台任务类,顾名思义就是异步任务。

AsyncTask直接继承于Object类,位置为android.os.AsyncTask。要使用AsyncTask工作我们要提供三个泛型参数,并重载几个方法(至少重载一个)。

/////////////

android提供了一套专门用于异步处理的类。即:AynsTask类。使用这个类可以为耗时程序开辟一个新线程进行处理,处理完时返回。
其实,AsynTask类就是对Thread类的一个封装,并且加入了一些新的方法。编程时,两者都可以实现同样的功能。本文后面将对AsynTask和Thread进行比较。
1、AsynTask类结构
asysTask类主要用到的几个内部回调函数有:
doInBackGround()

onPreExecute()

onPostExecute()

onProgressUpdate()
复制代码
正是这几个回调函数构成了AsynTask类的使用逻辑结构。
注意:每个AsynTask子类必须至少复写doInBackGround()方法。
2、回调逻辑关系
调用关系如下图:


1>主线程调用AsynTask子类实例的execute()方法后,首先会调用onPreExecute()方法。onPreExecute()在主线程中运行,可以用来写一些开始提示代码。
2>之后启动新线程,调用doInBackground()方法,进行异步数据处理。
3>处理完毕之后异步线程结束,在主线程中调用onPostExecute()方法。onPostExecute()可以进行一些结束提示处理。
补充:在doInBackground()方法异步处理的时候,如果希望通知主线程一些数据(如:处理进度)。这时,可以调用publishProgress()方法。这时,主线程会调用AsynTask子类的onProgressUpdate()方法进行处理。
3、各个函数间数据的传递
通过上面的调用关系,我们就可以大概看出一些数据传递关系。如下:
  execute()向doInBackground()传递。
  doInBackground()的返回值会传递给onPostExecute()。
  publishProgress()向progressUpdate()传递。

要点:为了调用关系明确及安全,AsynTask类在继承时要传入3个泛型。第一个泛型对应execute()向doInBackground()的传递类型。第二个泛型对应doInBackground()的返回类型和传递给onPostExecute()的类型。第三个泛型对应publishProgress()向progressUpdate()传递的类型。
传递的数据都是对应类型的数组,数组都是可变长的哦。可以根据具体情况使用。

AsyncTask定义了三种泛型类型 Params,Progress和Result。

  • Params 启动任务执行的输入参数,比如HTTP请求的URL。

  • Progress 后台任务执行的百分比。

  • Result 后台执行任务最终返回的结果,比如String。

使用过AsyncTask 的同学都知道一个异步加载数据最少要重写以下这两个方法:

  • doInBackground(Params…) 后台执行,比较耗时的操作都可以放在这里。注意这里不能直接操作UI。此方法在后台线程执行,完成任务的主要工作,通常需要较长的时间。在执行过程中可以调用publicProgress(Progress…)来更新任务的进度。

  • onPostExecute(Result) 相当于Handler 处理UI的方式,在这里面可以使用在doInBackground 得到的结果处理操作UI。 此方法在主线程执行,任务执行的结果作为此方法的参数返回

有必要的话你还得重写以下这三个方法,但不是必须的:

  • onProgressUpdate(Progress…) 可以使用进度条增加用户体验度。 此方法在主线程执行,用于显示任务执行的进度。

  • onPreExecute() 这里是最终用户调用Excute时的接口,当任务执行之前开始调用此方法,可以在这里显示进度对话框。

  • onCancelled() 用户调用取消时,要做的操作

使用AsyncTask类,以下是几条必须遵守的准则:

  • Task的实例必须在UI thread中创建;

  • execute方法必须在UI thread中调用;

  • 不要手动的调用onPreExecute(), onPostExecute(Result),doInBackground(Params...), onProgressUpdate(Progress...)这几个方法;

  • 该task只能被执行一次,否则多次调用时将会出现异常;

一个超简单的理解 AsyncTask 的例子:

main.xml

[java]view plaincopy

<OBJECT id=ZeroClipboardMovie_1 data="http://static.blog.csdn.net/scripts/ZeroClipboard/ZeroClipboard.swf" width=18 align=middle height=18 type=application/x-shockwave-flash bgcolor="#ffffff">

  1. <?xmlversion="1.0"encoding="utf-8"?>

  2. <LinearLayoutxmlns:android="http://schemas.android.com/apk/res/android"

  3. android:orientation="vertical"

  4. android:layout_width="fill_parent"

  5. android:layout_height="fill_parent"

  6. >

  7. <TextView

  8. android:id="@+id/textView01"

  9. android:layout_width="fill_parent"

  10. android:layout_height="wrap_content"

  11. />

  12. <ProgressBar

  13. android:id="@+id/progressBar02"

  14. android:layout_width="fill_parent"

  15. android:layout_height="wrap_content"

  16. style="?android:attr/progressBarStyleHorizontal"

  17. />

  18. <Button

  19. android:id="@+id/button03"

  20. android:layout_width="fill_parent"

  21. android:layout_height="wrap_content"

  22. android:text="更新progressbar"

  23. />

  24. </LinearLayout>


MainActivity.java

[html]view plaincopy

<OBJECT id=ZeroClipboardMovie_2 data="http://static.blog.csdn.net/scripts/ZeroClipboard/ZeroClipboard.swf" width=18 align=middle height=18 type=application/x-shockwave-flash bgcolor="#ffffff">

  1. packagevic.wong.main;

  2. importandroid.app.Activity;

  3. importandroid.os.Bundle;

  4. importandroid.view.View;

  5. importandroid.view.View.OnClickListener;

  6. importandroid.widget.Button;

  7. importandroid.widget.ProgressBar;

  8. importandroid.widget.TextView;

  9. publicclassMainActivityextendsActivity{

  10. privateButtonbutton;

  11. privateProgressBarprogressBar;

  12. privateTextViewtextView;

  13. @Override

  14. publicvoidonCreate(BundlesavedInstanceState){

  15. super.onCreate(savedInstanceState);

  16. setContentView(R.layout.main);

  17. button=(Button)findViewById(R.id.button03);

  18. progressBar=(ProgressBar)findViewById(R.id.progressBar02);

  19. textView=(TextView)findViewById(R.id.textView01);

  20. button.setOnClickListener(newOnClickListener(){

  21. @Override

  22. publicvoidonClick(Viewv){

  23. ProgressBarAsyncTaskasyncTask=newProgressBarAsyncTask(textView,progressBar);

  24. asyncTask.execute(1000);

  25. }

  26. });

  27. }

  28. }


NetOperator.java

[html]view plaincopy

<OBJECT id=ZeroClipboardMovie_3 data="http://static.blog.csdn.net/scripts/ZeroClipboard/ZeroClipboard.swf" width=18 align=middle height=18 type=application/x-shockwave-flash bgcolor="#ffffff">

  1. packagevic.wong.main;

  2. //模拟网络环境

  3. publicclassNetOperator{

  4. publicvoidoperator(){

  5. try{

  6. //休眠1秒

  7. Thread.sleep(1000);

  8. }catch(InterruptedExceptione){

  9. //TODOAuto-generatedcatchblock

  10. e.printStackTrace();

  11. }

  12. }

  13. }


ProgressBarAsyncTask .java

[html]view plaincopy

<OBJECT id=ZeroClipboardMovie_4 data="http://static.blog.csdn.net/scripts/ZeroClipboard/ZeroClipboard.swf" width=18 align=middle height=18 type=application/x-shockwave-flash bgcolor="#ffffff">

  1. packagevic.wong.main;

  2. importandroid.os.AsyncTask;

  3. importandroid.widget.ProgressBar;

  4. importandroid.widget.TextView;

  5. /**

  6. *生成该类的对象,并调用execute方法之后

  7. *首先执行的是onProExecute方法

  8. *其次执行doInBackgroup方法

  9. *

  10. */

  11. publicclassProgressBarAsyncTaskextendsAsyncTask<Integer,Integer,String>{

  12. privateTextViewtextView;

  13. privateProgressBarprogressBar;

  14. publicProgressBarAsyncTask(TextViewtextView,ProgressBarprogressBar){

  15. super();

  16. this.textView=textView;

  17. this.progressBar=progressBar;

  18. }

  19. /**

  20. *这里的Integer参数对应AsyncTask中的第一个参数

  21. *这里的String返回值对应AsyncTask的第三个参数

  22. *该方法并不运行在UI线程当中,主要用于异步操作,所有在该方法中不能对UI当中的空间进行设置和修改

  23. *但是可以调用publishProgress方法触发onProgressUpdate对UI进行操作

  24. */

  25. @Override

  26. protectedStringdoInBackground(Integer...params){

  27. NetOperatornetOperator=newNetOperator();

  28. inti=0;

  29. for(i=10;i<=100;i+=10){

  30. netOperator.operator();

  31. publishProgress(i);

  32. }

  33. returni+params[0].intValue()+"";

  34. }

  35. /**

  36. *这里的String参数对应AsyncTask中的第三个参数(也就是接收doInBackground的返回值)

  37. *在doInBackground方法执行结束之后在运行,并且运行在UI线程当中可以对UI空间进行设置

  38. */

  39. @Override

  40. protectedvoidonPostExecute(Stringresult){

  41. textView.setText("异步操作执行结束"+result);

  42. }

  43. //该方法运行在UI线程当中,并且运行在UI线程当中可以对UI空间进行设置

  44. @Override

  45. protectedvoidonPreExecute(){

  46. textView.setText("开始执行异步线程");

  47. }

  48. /**

  49. *这里的Intege参数对应AsyncTask中的第二个参数

  50. *在doInBackground方法当中,,每次调用publishProgress方法都会触发onProgressUpdate执行

  51. *onProgressUpdate是在UI线程中执行,所有可以对UI空间进行操作

  52. */

  53. @Override

  54. protectedvoidonProgressUpdate(Integer...values){

  55. intvlaue=values[0];

  56. progressBar.setProgress(vlaue);

  57. }

  58. }

更多相关文章

  1. Android源码获取方法
  2. Handler
  3. Android中程序与Service交互的方式——总结
  4. Android控件抖动效果
  5. AsyncTask异步执行
  6. android自动屏幕旋转流程分析
  7. Android的webview研究
  8. 浅谈Java中Collections.sort对List排序的两种方法
  9. Python list sort方法的具体使用

随机推荐

  1. MySQL 5.6 MRR 的存储过程完美诠释
  2. Amoeba for MySQL---分布式数据库Proxy解
  3. [MySQL复制异常]Cannot execute statemen
  4. MySQL用户管理(5.7.20-winx64)
  5. oracle中decode函数 VS mysql中的if函数
  6. mysql官方文档之Range Optimization
  7. MySqli 中预处理类 stmt
  8. 如何使用另一个表中的多个列替换表中的一
  9. 哪个更好的大查询或多个小查询?
  10. SQL:通过将两个列映射到彼此来更新表。