又是一段悲伤的往事,一次面试过程中面试官用一口印度英语问我,Do you know AsyncTask?take a example for using it。由于南北地方差异,我听了好半天没听懂,就说我不知道,我没用过,哎,现在想想真难。
what is AsyncTask?AsyncTask是一种后台线程,是android提供的轻量级的异步类,可以直接继承AsyncTask,在类中实现异步操作,并提供接口反馈当前异步执行的程度(可以通过接口实现UI进度更新),最后反馈执行的结果给UI主线程。
what is different between AsyncTask and Handler? Android的AsyncTask比Handler更轻量级一些,适用于简单的异步处理。当你你从后台去更行界面的时候就应该考虑AsyncTask了。
AsyncTask的使用包括4个步骤:
(1)在onPreExecutive()方法中执行任何设置工作,此方法在主线程上执行。
(2)使用doInBackgroud()运行后台线程,线程创建全部在后台完成。
(3)使用publishProgress()和onProgressUpdate()更新进度。
(4)使用结果在onPostExecute()中更新用户界面,此方法在主线程中执行。
这样说有点官方化,我用例子来说明吧。
public class HttpActivity extends Activity {
private DownloadImageTask diTask;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
}
public void doClick(View view) {
if (diTask != null) {
AsyncTask.Status diStatus = diTask.getStatus();
Log.v("doClick", "diTask status is " + diStatus);
if (diStatus != AsyncTask.Status.FINISHED) {
Log.v("doClick", "... no need to start a new task");
return;
}
}
diTask = new DownloadImageTask(this);
diTask.execute("URL");
}
}
主界面很简单,又是一个点击事件,然后执行diTask去下载URL上面的图片。
public class DownloadImageTask extends AsyncTask<String, Integer, Bitmap> {
private Context mContext;
DownloadImageTask(Context context) {
mContext = context;
}
protected void onPreExecute() {
}
protected Bitmap doInBackground(String... urls) {
return downloadImage(urls);
}
protected void onProgressUpdate(Integer... progress) {
TextView mText = (TextView) ((Activity) mContext)
.findViewById(R.id.text);
mText.setText("Progress so far: " + progress[0]);
}
protected void onPostExecute(Bitmap result) {
if (result != null) {
ImageView mImage = (ImageView) ((Activity) mContext)
.findViewById(R.id.image);
mImage.setImageBitmap(result);
} else {
TextView errorMsg = (TextView) ((Activity) mContext)
.findViewById(R.id.errorMsg);
errorMsg.setText("Problem downloading image. Please try again later.");
}
}
private Bitmap downloadImage(String... urls) {
HttpClient httpClient = CustomHttpClient.getHttpClient();
try {
HttpGet request = new HttpGet(urls[0]);
HttpParams params = new BasicHttpParams();
HttpConnectionParams.setSoTimeout(params, 60000); // 1 minute
request.setParams(params);
publishProgress(25);
HttpResponse response = httpClient.execute(request);
publishProgress(50);
byte[] image = EntityUtils.toByteArray(response.getEntity());
publishProgress(75);
Bitmap mBitmap = BitmapFactory.decodeByteArray(image, 0,
image.length);
publishProgress(100);
return mBitmap;
} catch (IOException e) {
e.printStackTrace();
}
return null;
}
}
然后就是实现AsyncTask,这里我还做了一个进度条,时时更新主界面UI的下载进度。
public class CustomHttpClient {
private static HttpClient customHttpClient;
/** A private Constructor prevents any other class from instantiating. */
private CustomHttpClient() {
}
public static synchronized HttpClient getHttpClient() {
if (customHttpClient == null) {
HttpParams params = new BasicHttpParams();
HttpProtocolParams.setVersion(params, HttpVersion.HTTP_1_1);
HttpProtocolParams.setContentCharset(params, HTTP.DEFAULT_CONTENT_CHARSET);
HttpProtocolParams.setUseExpectContinue(params, true);
ConnManagerParams.setTimeout(params, 1000);
HttpConnectionParams.setConnectionTimeout(params, 5000);
HttpConnectionParams.setSoTimeout(params, 10000);
SchemeRegistry schReg = new SchemeRegistry();
schReg.register(new Scheme("http",
PlainSocketFactory.getSocketFactory(), 80));
schReg.register(new Scheme("https",
SSLSocketFactory.getSocketFactory(), 443));
ClientConnectionManager conMgr = new
ThreadSafeClientConnManager(params,schReg);
customHttpClient = new DefaultHttpClient(conMgr, params);
}
return customHttpClient;
}
}
这里是自定义HttpClient,最后点击就可以实现了网络异步图片下载,并且更新下载进度条,多也不知道该怎么讲述这个AsyncTask,只是知道它提供更方便的更新UI的方法,你可以从复写类里面看到,只要会用,知道怎么用,并且用在该用的地方就可以了,重要的是面试的时候知道这么个东西,反正我是很少用到。