昨天把Handler又看了一遍,以前不是特别懂,现在基本上差不多了,博客真是个好东西,不仅加深印象和理解还能永久保存。所以今天想把AsyncTask再过一遍。前面讲过一篇AsyncTask与Handler的比对区别点击打开链接。昨天还对Handler重新学了一遍,各种的看视频、看文档、看看别人理解的。想着自己该如何理解。点击打开链接
onPreExecute(), 该方法将在执行实际的后台操作前被UI 线程调用。可以在该方法中做一些准备工作,如在界面上显示一个进度条,或者一些控件的实例化,这个方法可以不用实现。
doInBackground(Params...), 将在onPreExecute 方法执行后马上执行,该方法运行在后台线程中。这里将主要负责执行那些很耗时的后台处理工作。可以调用 publishProgress方法来更新实时的任务进度。该方法是抽象方法,子类必须实现。
onProgressUpdate(Progress...),在publishProgress方法被调用后,UI 线程将调用这个方法从而在界面上展示任务的进展情况,例如通过一个进度条进行展示。
AsyncTask是一个异步任务,我们知道在子线程中是不能更新UI的,必须要在UI线程中,但是如果我们想要下载一些网络图片等等,我们可以在子线程中,下载完成之后我们需要更新UI了,这时候就需要子线程与主线程进行通讯,主线程更新UI。前面提到使用Handler机制可以来完成,但是有点麻烦。有没有什么方法可以一步到位呢?这就是AsyncTask。
注意:官方推荐AsyncTask尽量做一些下载量小的时间短的任务。长时间大容量的下载推荐使用线程池。
实现AsyncTask
之前写过的,大概就是下面几个过程, 主要四个实现接口:onPreExecute(), 该方法将在执行实际的后台操作前被UI 线程调用。可以在该方法中做一些准备工作,如在界面上显示一个进度条,或者一些控件的实例化,这个方法可以不用实现。
doInBackground(Params...), 将在onPreExecute 方法执行后马上执行,该方法运行在后台线程中。这里将主要负责执行那些很耗时的后台处理工作。可以调用 publishProgress方法来更新实时的任务进度。该方法是抽象方法,子类必须实现。
onProgressUpdate(Progress...),在publishProgress方法被调用后,UI 线程将调用这个方法从而在界面上展示任务的进展情况,例如通过一个进度条进行展示。
onPostExecute(Result), 在doInBackground 执行完成后,onPostExecute 方法将被UI 线程调用,后台的计算结果将通过该方法传递到UI 线程,并且在界面上展示给用户.。
实例:从网络中加载一张图片
演示创建AsyncTask,看一下上面的几个接口的调用顺序。
public class MainActivity extends Activity {
private ImageView imageView1;
private ProgressBar progressBar;
private Button button1;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Log.i("info", "onCreate");
findViews();
}
private void findViews() {
imageView1 = (ImageView)findViewById( R.id.imageView1 );
progressBar = (ProgressBar)findViewById( R.id.progressBar );
button1 = (Button)findViewById( R.id.button1 );
button1.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
new MyAsyncTask().execute();
}
});
}
/**
* AsyncTask<String, Void, Bitmap>
* 第一个参数String:实现AsyncTask时传入的参数
* 第二个参数Void: 更新进度返回的当前值
* 第三个参数Bitmap:异步任务返回的值,这里加载一张图片所以返回的是Bitmap
*/
private class MyAsyncTask extends AsyncTask<String, Void, Bitmap>{
//异步任务开始之前调用
@Override
protected void onPreExecute() {
Log.i("info", "onPreExecute");
progressBar.setVisibility(View.VISIBLE);//显示进度
super.onPreExecute();
}
//必须重写,params是一个可变长的数组,用于接收传入的参数
@Override
protected Bitmap doInBackground(String... params) {
Log.i("info", "doInBackground");
String url="http://www.iyi8.com/uploadfile/2016/0225/20160225124617786.jpg";//网络图片地址
Bitmap bitmap=doHttpClient(url);//加载网络图片
//publishProgress();
return bitmap;
}
//在doInBackground之后调用,
//Bitmap result里面的result是从doInBackground自动拿过来的
//在此方法里面可以直接更新UI
@Override
protected void onPostExecute(Bitmap result) {
Log.i("info", "onPostExecute");
progressBar.setVisibility(View.INVISIBLE);//隐藏进度
imageView1.setImageBitmap(result);//设置从doInBackground返回的Bitmap。
super.onPostExecute(result);
publishProgress(null);
}
@Override
protected void onProgressUpdate(Void... values) {
Log.i("info", "onProgressUpdate");
super.onProgressUpdate(values);
}
}
//从网络中获取图片
private Bitmap doHttpClient(String url){
Bitmap bitmap=null;
HttpClient httpClient = new DefaultHttpClient();//创建一个默认的httpclient
HttpClientParams.setCookiePolicy(httpClient.getParams(), CookiePolicy.BROWSER_COMPATIBILITY);
HttpGet httpGet = new HttpGet(url);//创建get请求
InputStream is = null;
try {
HttpResponse httpResponse = httpClient.execute(httpGet);//执行请求
HttpEntity httpEntity = httpResponse.getEntity();//得到响应内容
BufferedHttpEntity bufferedHttpEntity = new BufferedHttpEntity(httpEntity);
is = bufferedHttpEntity.getContent();
if (is != null) {
bitmap = BitmapFactory.decodeStream(is);//转为bitmap
return bitmap;
}
} catch (ClientProtocolException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
try {
is.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return bitmap;
}
}
运行一下就可以加载出我们的图片了。这几个回调方法的调用顺序是
当然还可以异步加载其他的好多好多信息。那就根据自己的需要了。未完待续