线程分为主线程和子线程,主线程主要处理和界面相关的事情,而子线程往往用于执行耗时操作。我们今天所说的AsyncTask其实是一个轻量级的异步任务类,它可以在线程池中执行后台任务,然后把执行的进度和最终结果传递给主线程并在主线程中更新UI。我们首先了解一下AsyncTask提供的四个核心方法,然后举一个小例子加深一下印象。
public abstract class AsyncTask<Params,Progress,Result>
AsyncTask是一个抽象的泛型类,它提供了Params,Progress,Result这三个参数,其中Params:表示参数的类型,Progress:表示后台任务的执行进度的类型,Result:后台任务的返回结果类型。如果确实不需要传递具体的参数,可以用void来代替。
AsyncTask的四个核心方法:
1:onPreExecute(),在主线程中执行,在异步任务执行之前次方法会调用,一般用于做一些准备工作。
2:doInBackground(Params...params),此方法用于异步任务,params参数表示异步任务的输入参数,在此方法中可以通过publicProgress()方法来更新任务的进度 publicProgress方法会调用onProgressUpdate方法。另外此方法需要返回计算结果给onPostExecute方法。
3:onProgressUpdate(Progress...values),在主线程中执行,当后台任务发生变化时会调用次方法。
4:onPostExecute(Result result),在主线程中执行,在异步任务完成之后,此方法会被调用,其中,result参数是后台任务返回值,即doInBackground的返回值。
上面的几种方法,onPreExecute()先执行,接着是doInBackground,之后是onPostExecute方法。
下面就举一个例子来验证一下这四种方法的使用。
我们创建一个工程,其中有两个类,首先看一下ImageTest.java这个类
package com.example.asynctasktest;
import java.io.BufferedInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.MalformedURLException;
import java.net.URLConnection;
import android.app.Activity;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.os.AsyncTask;
import android.os.Bundle;
import android.view.View;
import android.widget.ImageView;
import android.widget.ProgressBar;
import java.net.URL;
public class ImageTest extends Activity{
private ImageView mImageView;
private ProgressBar mProgressBar;
private static String URL = "http://blog.csdn.net/lyjit";
@Override
protected void onCreate(Bundle savedInstanceState) {
// TODO Auto-generated method stub
super.onCreate(savedInstanceState);
setContentView(R.layout.image);
mImageView = (ImageView) findViewById(R.id.image);
mProgressBar = (ProgressBar) findViewById(R.id.progressbar);
new MyAsycnTesk().execute(URL);
}
class MyAsycnTesk extends AsyncTask<String, Void, Bitmap>{
@Override
protected void onPreExecute() {
super.onPreExecute();
mProgressBar.setVisibility(View.VISIBLE);
}
@Override
protected void onPostExecute(Bitmap result) {
super.onPostExecute(result);
//操作UI
mProgressBar.setVisibility(View.GONE);
mImageView.setImageBitmap(result);
}
@Override
protected Bitmap doInBackground(String... arg0) {//用作耗时操作使用
//获取传递来的参数
String url = arg0[0];// 取出对应的URL
Bitmap bitmap = null;
URLConnection connection;
InputStream is;
try {
connection = new URL(url).openConnection();
is = connection.getInputStream();
BufferedInputStream bis = new BufferedInputStream(is);
//通过decodeStream解析输入流
bitmap = BitmapFactory.decodeStream(bis);
//关闭输入流
is.close();
bis.close();
} catch (MalformedURLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
//将bitmap作为返回值传递
return bitmap;
}
}
}
上面的每个方法我都注释详细了,大家一看就会明白,其中 doInBackground(String... arg0) 中包含的...字样表示参数的数量不定,是一种数组型参数。然后看一下R.layout.image的布局
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
>
<ImageView
android:id="@+id/image"
android:layout_width="match_parent"
android:layout_height="match_parent"
/>
<ProgressBar
android:id="@+id/progressbar"
android:visibility="gone"
android:layout_gravity="center_vertical"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
/>
</RelativeLayout>
然后在Activity.java中直接启动ImageTest.java就可以看到效果了。
最后别忘了添加一下网络的权限:<application android:name="android.permission.INTERNET"/>
使用AsyncTask时需要注意的问题:
- AsyncTask的类必须在主线程中加载
- AsyncTask的对象必须在主线程中创建
- execute方法必须在UI线程调用
- 不要在程序中直接调用四个核心的方法。系统的方法不能被调用的!
- 一个AsyncTask对象只能执行一次,只能调用一次execute方法,否则会报运行异常