Android AsyncTask的使用介绍与示例
2014-02-21 10:45
501 查看
(介绍部分转自《Android
AsyncTask完全解析,带你从源码的角度彻底理解》,有改动)
我们都知道,Android UI是线程不安全的,如果想要在子线程里进行UI操作,就需要借助Android的异步消息处理机制。之前我也写过了一篇文章从源码层面分析了Android的异步消息处理机制,感兴趣的朋友可以参考Android
Handler、Message完全解析,带你从源码的角度彻底理解 。
不过为了更加方便我们在子线程中更新UI元素,Android从1.5版本就引入了一个AsyncTask类,使用它就可以非常灵活方便地从子线程切换到UI线程,我们本篇文章的主角也就正是它了。
AsyncTask很早就出现在Android的API里了,所以我相信大多数朋友对它的用法都已经非常熟悉。不过今天我还是准备从AsyncTask的基本用法开始讲起,然后我们再来一起分析下AsyncTask源码,看看它是如何实现的,最后我会介绍一些关于AsyncTask你所不知道的秘密。
一、AsyncTask的基本用法
首先来看一下AsyncTask的基本用法,由于AsyncTask是一个抽象类,所以如果我们想使用它,就必须要创建一个子类去继承它。在继承时我们可以为AsyncTask类指定三个泛型参数,这三个参数的用途如下:
1. Params
在执行AsyncTask时需要传入的参数,可用于在后台任务中使用。
2. Progress
后台任务执行时,如果需要在界面上显示当前的进度,则使用这里指定的泛型作为进度单位。
3. Result
当任务执行完毕后,如果需要对结果进行返回,则使用这里指定的泛型作为返回值类型。
因此,一个最简单的自定义AsyncTask就可以写成如下方式:
当然,目前我们自定义的DownloadTask还是一个空任务,并不能进行任何实际的操作,我们还需要去重写AsyncTask中的几个方法才能完成对任务的定制。经常需要去重写的方法有以下四个:
1. onPreExecute()
这个方法会在后台任务开始执行之间调用,用于进行一些界面上的初始化操作,比如显示一个进度条对话框等。
2. doInBackground(Params...)
这个方法中的所有代码都会在子线程中运行,我们应该在这里去处理所有的耗时任务。任务一旦完成就可以通过return语句来将任务的执行结果进行返回,如果AsyncTask的第三个泛型参数指定的是Void,就可以不返回任务执行结果。注意,在这个方法中是不可以进行UI操作的,如果需要更新UI元素,比如说反馈当前任务的执行进度,可以调用publishProgress(Progress...)方法来完成。
3. onProgressUpdate(Progress...)
当在后台任务中调用了publishProgress(Progress...)方法后,这个方法就很快会被调用,方法中携带的参数就是在后台任务中传递过来的。在这个方法中可以对UI进行操作,利用参数中的数值就可以对界面元素进行相应的更新。
4. onPostExecute(Result)
当后台任务执行完毕并通过return语句进行返回时,这个方法就很快会被调用。返回的数据会作为参数传递到此方法中,可以利用返回的数据来进行一些UI操作,比如说提醒任务执行的结果,以及关闭掉进度条对话框等。
5.onCancelled()
在用户取消线程操作的时候调用。在主线程中调用onCancelled()的时候调用。
为了正确的使用AsyncTask类,以下是几条必须遵守的准则(来自Android API):
1) Task的实例必须在UI 线程中创建。
2) execute方法必须在UI 线程中调用。
3) 不要手动的调用onPreExecute(), onPostExecute(Result),doInBackground(Params...), onProgressUpdate(Progress...)这几个方法,需要在UI线程中实例化这个task来调用。
4) 该task只能被执行一次,否则多次调用时将会出现异常。
(例子转自:《Android中AsyncTask的简单用法》http://blog.csdn.net/cjjky/article/details/6684959)
二、一个AsyncTask使用例子
一个使用AsyncTask下载图片的例子
布局文件如下:
程序的运行结果截图:
AsyncTask完全解析,带你从源码的角度彻底理解》,有改动)
我们都知道,Android UI是线程不安全的,如果想要在子线程里进行UI操作,就需要借助Android的异步消息处理机制。之前我也写过了一篇文章从源码层面分析了Android的异步消息处理机制,感兴趣的朋友可以参考Android
Handler、Message完全解析,带你从源码的角度彻底理解 。
不过为了更加方便我们在子线程中更新UI元素,Android从1.5版本就引入了一个AsyncTask类,使用它就可以非常灵活方便地从子线程切换到UI线程,我们本篇文章的主角也就正是它了。
AsyncTask很早就出现在Android的API里了,所以我相信大多数朋友对它的用法都已经非常熟悉。不过今天我还是准备从AsyncTask的基本用法开始讲起,然后我们再来一起分析下AsyncTask源码,看看它是如何实现的,最后我会介绍一些关于AsyncTask你所不知道的秘密。
一、AsyncTask的基本用法
首先来看一下AsyncTask的基本用法,由于AsyncTask是一个抽象类,所以如果我们想使用它,就必须要创建一个子类去继承它。在继承时我们可以为AsyncTask类指定三个泛型参数,这三个参数的用途如下:
1. Params
在执行AsyncTask时需要传入的参数,可用于在后台任务中使用。
2. Progress
后台任务执行时,如果需要在界面上显示当前的进度,则使用这里指定的泛型作为进度单位。
3. Result
当任务执行完毕后,如果需要对结果进行返回,则使用这里指定的泛型作为返回值类型。
因此,一个最简单的自定义AsyncTask就可以写成如下方式:
class DownloadTask extends AsyncTask<Void, Integer, Boolean> { …… }这里我们把AsyncTask的第一个泛型参数指定为Void,表示在执行AsyncTask的时候不需要传入参数给后台任务。第二个泛型参数指定为Integer,表示使用整型数据来作为进度显示单位。第三个泛型参数指定为Boolean,则表示使用布尔型数据来反馈执行结果。
当然,目前我们自定义的DownloadTask还是一个空任务,并不能进行任何实际的操作,我们还需要去重写AsyncTask中的几个方法才能完成对任务的定制。经常需要去重写的方法有以下四个:
1. onPreExecute()
这个方法会在后台任务开始执行之间调用,用于进行一些界面上的初始化操作,比如显示一个进度条对话框等。
2. doInBackground(Params...)
这个方法中的所有代码都会在子线程中运行,我们应该在这里去处理所有的耗时任务。任务一旦完成就可以通过return语句来将任务的执行结果进行返回,如果AsyncTask的第三个泛型参数指定的是Void,就可以不返回任务执行结果。注意,在这个方法中是不可以进行UI操作的,如果需要更新UI元素,比如说反馈当前任务的执行进度,可以调用publishProgress(Progress...)方法来完成。
3. onProgressUpdate(Progress...)
当在后台任务中调用了publishProgress(Progress...)方法后,这个方法就很快会被调用,方法中携带的参数就是在后台任务中传递过来的。在这个方法中可以对UI进行操作,利用参数中的数值就可以对界面元素进行相应的更新。
4. onPostExecute(Result)
当后台任务执行完毕并通过return语句进行返回时,这个方法就很快会被调用。返回的数据会作为参数传递到此方法中,可以利用返回的数据来进行一些UI操作,比如说提醒任务执行的结果,以及关闭掉进度条对话框等。
5.onCancelled()
在用户取消线程操作的时候调用。在主线程中调用onCancelled()的时候调用。
为了正确的使用AsyncTask类,以下是几条必须遵守的准则(来自Android API):
1) Task的实例必须在UI 线程中创建。
2) execute方法必须在UI 线程中调用。
3) 不要手动的调用onPreExecute(), onPostExecute(Result),doInBackground(Params...), onProgressUpdate(Progress...)这几个方法,需要在UI线程中实例化这个task来调用。
4) 该task只能被执行一次,否则多次调用时将会出现异常。
(例子转自:《Android中AsyncTask的简单用法》http://blog.csdn.net/cjjky/article/details/6684959)
二、一个AsyncTask使用例子
一个使用AsyncTask下载图片的例子
package com.andyidea.demo; import android.app.Activity; import android.os.AsyncTask; import android.os.Bundle; import android.view.View; import android.widget.Button; import android.widget.ProgressBar; import android.widget.TextView; public class MainActivity extends Activity { Button download; ProgressBar pb; TextView tv; /** Called when the activity is first created. */ @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.main); pb=(ProgressBar)findViewById(R.id.pb); tv=(TextView)findViewById(R.id.tv); download = (Button)findViewById(R.id.download); download.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { DownloadTask dTask = new DownloadTask(); dTask.execute(100); } }); } class DownloadTask extends AsyncTask<Integer, Integer, String>{ //后面尖括号内分别是参数(例子里是线程休息时间),进度(publishProgress用到),返回值 类型 @Override protected void onPreExecute() { //第一个执行方法 super.onPreExecute(); } @Override protected String doInBackground(Integer... params) { //第二个执行方法,onPreExecute()执行完后执行 for(int i=0;i<=100;i++){ pb.setProgress(i); publishProgress(i);//调用onProgressUpdate(Integer... progress)方法 try { Thread.sleep(params[0]); } catch (InterruptedException e) { e.printStackTrace(); } } return "执行完毕"; } @Override protected void onProgressUpdate(Integer... progress) { //这个函数在doInBackground调用publishProgress时触发,虽然调用时只有一个参数 //但是这里取到的是一个数组,所以要用progesss[0]来取值 //第n个参数就用progress 来取值 tv.setText(progress[0]+"%"); super.onProgressUpdate(progress); } @Override protected void onPostExecute(String result) { //doInBackground返回时触发,换句话说,就是doInBackground执行完后触发 //这里的result就是上面doInBackground执行后的返回值,所以这里是"执行完毕" setTitle(result); super.onPostExecute(result); } } }
布局文件如下:
<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:orientation="vertical" android:layout_width="fill_parent" android:layout_height="fill_parent" > <TextView android:layout_width="fill_parent" android:layout_height="wrap_content" android:text="Hello , Welcome to Andy's Blog!"/> <Button android:id="@+id/download" android:layout_width="fill_parent" android:layout_height="wrap_content" android:text="Download"/> <TextView android:id="@+id/tv" android:layout_width="fill_parent" android:layout_height="wrap_content" android:text="当前进度显示"/> <ProgressBar android:id="@+id/pb" android:layout_width="fill_parent" android:layout_height="wrap_content" style="?android:attr/progressBarStyleHorizontal"/> </LinearLayout>
程序的运行结果截图:
相关文章推荐
- Android系统下载管理DownloadManager功能介绍及使用示例
- Android系统下载管理DownloadManager功能介绍及使用示例
- android Paint和Color类介绍 使用示例
- android AsyncTask介绍 详解AsyncTask的使用 使用实例---加载网络图片
- Android Rsa数据加解密的介绍与使用示例
- Android系统下载管理DownloadManager功能介绍及使用示例
- Android异步处理二:AsynTask介绍和使用AsyncTask异步更新UI界面
- Android系统下载管理DownloadManager功能介绍及使用示例
- android AsyncTask的使用介绍
- Android系统下载管理DownloadManager功能介绍及使用示例
- Android 广播介绍以及使用示例
- Android基础 -- AsyncTask介绍和使用
- Android 广播介绍以及使用示例
- android AsyncTask使用介绍。
- Android系统下载管理DownloadManager功能介绍及使用示例
- android 使用asynctask结合fragment更新UI(另附线程池管理示例)
- Android-AsyncTask简单介绍和使用
- Android系统下载管理DownloadManager功能介绍及使用示例
- android Paint和Color类介绍 使用示例
- Android 广播介绍以及使用示例