又是一段悲伤的往事,一次面试过程中面试官用一口印度英语问我,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的方法,你可以从复写类里面看到,只要会用,知道怎么用,并且用在该用的地方就可以了,重要的是面试的时候知道这么个东西,反正我是很少用到。