您的位置:首页 > 移动开发 > Android开发

Android_AsyncTask

2016-06-06 14:13 453 查看

Android_AsyncTask

我在上一篇的Blog中介绍了Android中多线程之间的通信–Handler消息机制,如果你不是那么的理解。今天就让我们学习一下,Android帮我们做了很好的一个封装工具—AsyncTask(AsyncTask可以十分简单的从子线程切换到主线程。)

在学习AsyncTask之前,我们还是先了解一下AsyncTask是什么?使用它需要传入那些参数。和它都具有什么方法。

AsyncTask是一个自动在子线程执行任务,并且自动实现了在主线程对进度和结果更新的一个异步任务类,开发者只需要将不同的代码重写在不同的方法即可。

继承AsyncTask参数说明

AsyncTask是一个抽象类,通常需要自定义类,继承自AsyncTask,

在继承时,需要指定3个泛型的数据类型,分别表示:

1、(params)执行任务时所需要的参数的数据类型、

2、(Progress)执行任务过程中如果需要更新进度,表示进度的数据类型、

3、(Result)执行任务完成之后,结果的数据类型

部分任务可能不需要以上3种中的某些数据类型,通常使用Void类型进行标识。

AsyncTask中的方法

1、onPreExecute()

这个方法会在后台任务开始执行之前调用,用于进行一些界面上的初始化操作,比如显示一个进度条对话框。

2、doInBackground(Params …)

这个方法中的所有代码都是在子线程中运行,我们应该在这里去处理所有的耗时任务。任务一单完成就可以通过return语句来讲任务的执行结果返回,如果AsyncTask的第三个泛型参数指定的是Void,就可以不返回任务执行结果。注意,在这个方法中是不可以进行UI操作的,如果需要更新UI元素,比如说反馈当前任务的执行进度,可以调用publicProgress(Progress…)

3、onProgressUpdate(Progress…)

当在后台任务中调用了publicProgress(Progress…)方法后,这个方法就会很快被调用,方法中携带的参数就是在后台任务中传递过来的。在这个方法中可以对UI进行操作,利用参数中的数值可以对界面元素进行相应地更新。

4、onPostExecute(Result)

当后台任务执行完毕并通过return语句进行返回时,这个方法就很快会被调用。返回的数据会作为参数传递到此方法中,可以利用返回的数据来进行一些UI操作,比如关闭掉进度条对话框。

通过对上面对AsyncTask的讲解,你应该没有那么迷茫了,现在我们就通过一个小实例来具体的体会一下吧。我的这个实例很简单,就是点击按钮去下载网络中的一张图片,并显示在ImageView中。

1、下面先给大家我的activity_main.xml布局文件的代码:

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context="com.example.asynctasktest.MainActivity">

<Button
android:id="@+id/main_DownloadBtn"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="点击下载图片"
android:textSize="18sp" />
<ImageView
android:id="@+id/main_iv_show"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_below="@+id/main_DownloadBtn"
android:src="@mipmap/ic_launcher"/>
</RelativeLayout>


2、下面让我们来看一下MainActivity中的具体逻辑代码:

public class MainActivity extends Activity {
private Button downLoadBtn;
private ImageView ivShowImage;
//图片的URL
private String IMAGE_PATH = "http://d.hiphotos.baidu.com/image/w%3D2048/sign=232a6514be315c6043956cefb989ca13/c83d70cf3bc79f3d3b082d31b8a1cd11738b29c2.jpg";
private ProgressDialog dialog;

@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
//设置Activity没有标题栏
requestWindowFeature(Window.FEATURE_NO_TITLE);
setContentView(R.layout.activity_main);
downLoadBtn = (Button) findViewById(R.id.main_DownloadBtn);
ivShowImage = (ImageView) findViewById(R.id.main_iv_show);
dialog = new ProgressDialog(this);
//用户不可以点击取消
dialog.setCancelable(false);
dialog.setMessage("正在下载图片,请耐心等待--");
//显示一个百分比进度条,不加就显示默认的圈圈
dialog.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL);
downLoadBtn.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
new InnerAsyncTask().execute(IMAGE_PATH);
}
});
}

/***
* 自定义InnerAsyncTask继承AsyncTask
*/
class InnerAsyncTask extends AsyncTask<String, Integer, byte[]> {
//使用HttpURLConnection请求,我在AndroidStudio中没有发现HttpClient
HttpURLConnection connection = null;
URL url = null;
InputStream inputStream = null;
//返回的图片的内容
byte[] result = null;
ByteArrayOutputStream outputStream = new ByteArrayOutputStream();

@Override
protected void onPreExecute() {
super.onPreExecute();
//显示进度条
dialog.show();
}

@Override
protected byte[] doInBackground(String... params) {
try {
url = new URL(params[0]);
connection = (HttpURLConnection) url.openConnection();
int file_length = connection.getContentLength();
int totle_length = 0;
byte[] data = new byte[1024];
int len = 0;
if (connection.getResponseCode() == 200) {
inputStream = connection.getInputStream();
while ((len = inputStream.read(data)) != -1) {
totle_length += len;
int progress_value = (int) (totle_length / (float) file_length);
//发布刻度单位
publishProgress(progress_value);
outputStream.write(data, 0, len);
}
}
result = outputStream.toByteArray();
} catch (MalformedURLException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} finally {
if (connection != null) {
connection.disconnect();
}
}
return result;
}

@Override
protected void onProgressUpdate(Integer... values) {
super.onProgressUpdate(values);
//设置进度条的显示进度
dialog.setProgress(values[0]);
}

@Override
protected void onPostExecute(byte[] result) {
super.onPostExecute(result);
Bitmap bm = BitmapFactory.decodeByteArray(result, 0, result.length);
//给ImageView设置Bitmap对象
ivShowImage.setImageBitmap(bm);
//显示出来图片后将进度条消失
dialog.dismiss();
}
}
}


注意

AsyncTask的执行特性是一把双刃剑,当存在多个AsyncTask时,所有的AsyncTask会依据启动的顺序依次执行,而并不会存在多个任务的多个子线程同时运行的状况

如果你感觉上面的内容比较简单,可以看一下AsyncTask的源码讲解:

AsyncTask源码讲解
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: