本文主要是介绍Android中异步加载数据(二)AsyncTask异步更新界面,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!
Android中异步加载数据(二)AsyncTask异步更新界面
-
今天介绍第二种异步更新界面的方式:AsyncTask
官方文档:
AsyncTask enables proper and easy use of the UI thread. This class allows to perform background operations and publish results on the UI thread without having to manipulate threads and/or handlers.
AsyncTask能够更恰当和更简单的去使用UI线程。这个类允许执行后台操作和展现结果在UI线程上,无需操纵线程和/或处理程序。AsyncTask的内部实现是一个线程池,每个后台任务会提交到线程池中的线程执行,然后使用Thread+Handler的方式调用回调函数。
1.AsyncTask抽象出后台线程运行的五个状态:
分别是:1、准备运行,2、正在后台运行,3、进度更新,4、完成后台任务,5、取消任务,对于这五个阶段,AsyncTask提供了五个回调函数:
1、准备运行:onPreExecute(),该回调函数在任务被执行之后立即由UI线程调用。这个步骤通常用来建立任务,在用户接口(UI)上显示进度条。
2、正在后台运行:doInParams...),该回调函数由后台线程在onPreExecute()方法执行结束后立即调用。通常在这里执行耗时的后台计算。计算的结果必须由该函数返回,并被传递到onPostExecute()中。在该函数内也可以使用publishProgress(Progress...)来发布一个或多个进度单位(unitsof progress)。这些值将会在onProgressUpdate(Progress...)中被发布到UI线程。
3. 进度更新:onProgressUpdate(Progress...),该函数由UI线程在publishProgress(Progress...)方法调用完后被调用。一般用于动态地显示一个进度条。
4. 完成后台任务:onPostExecute(Result),当后台计算结束后调用。后台计算的结果会被作为参数传递给这一函数。
5、取消任务:onCancelled (),在调用AsyncTask的cancel()方法时调用
2.使用:
AsyncTask必须使用子类。子类会覆盖至少一个方法(doInParams…)),通常将覆盖第二个(onPostExecute(结果)。< /span>
AsyncTask的构造函数有三个模板参数:AsyncTask<Params, Progress, Result>
1.Params,传递给后台任务的参数类型。
2.Progress,后台计算执行过程中,进步单位(progress units)的类型。(就是后台程序已经执行了百分之几了。)
3.Result, 后台执行返回的结果的类型。
AsyncTask并不总是需要使用上面的全部3种类型。标识不使用的类型很简单,只需要使用Void类型即可。
001.
import
java.io.InputStream;
002.
import
java.net.HttpURLConnection;
003.
import
java.net.URL;
004.
import
android.app.Activity;
005.
import
android.graphics.Bitmap;
006.
import
android.graphics.BitmapFactory;
007.
import
android.os.AsyncTask;
008.
import
android.os.Bundle;
009.
import
android.view.View;
010.
import
android.view.View.OnClickListener;
011.
import
android.widget.Button;
012.
import
android.widget.ImageView;
013.
import
android.widget.ProgressBar;
014.
import
android.widget.Toast;
015.
/**
016.
* AsyncTask 实现异步加载图片
017.
* @author ZHF
018.
*
019.
*/
020.
public
class
MainActivity
extends
Activity {
021.
022.
public
static
final
String IMG_URL=
"http://images.51cto.com/images/index/Images/Logo.gif"
;
023.
Button btn_asynctask;
024.
ImageView imgView;
025.
ProgressBar progressBar;
026.
027.
@Override
028.
protected
void
onCreate(Bundle savedInstanceState) {
029.
super
.onCreate(savedInstanceState);
030.
setContentView(R.layout.activity_main);
031.
//加载控件
032.
imgView = (ImageView)
this
.findViewById(R.id.imageView);
033.
btn_asynctask = (Button)
this
.findViewById(R.id.btn_AsyncTask);
034.
progressBar = (ProgressBar)
this
.findViewById(R.id.progressBar);
035.
//绑定监听器
036.
btn_asynctask.setOnClickListener(
new
OnClickListener() {
037.
@Override
038.
public
void
onClick(View v) {
039.
GetImgTask getImgTask =
new
GetImgTask();
040.
getImgTask.execute(IMG_URL);
//执行该任务
041.
}
042.
});
043.
}
044.
045.
/**获取网络图片任务**/
046.
private
class
GetImgTask
extends
AsyncTask<String, Integer, Bitmap> {
047.
048.
/**在 doInParams...)之前被调用,在ui线程执行 **/
049.
@Override
050.
protected
void
onPreExecute() {
051.
imgView.setImageBitmap(
null
);
052.
progressBar.setProgress(
0
);
//进度条复位
053.
}
054.
055.
/**在后台线程中执行的任务**/
056.
@Override
057.
protected
Bitmap doInString... params) {
058.
059.
publishProgress(
0
);
//会调用onProgressUpdate更新界面
060.
061.
InputStream inputStream =
null
;
062.
Bitmap imgBitmap =
null
;
063.
try
{
064.
URL url =
new
URL(IMG_URL);
065.
if
(url !=
null
) {
066.
HttpURLConnection connection = (HttpURLConnection) url.openConnection();
067.
connection.setConnectTimeout(
2000
);
068.
connection.setDoInput(
true
);
069.
connection.setRequestMethod(
"GET"
);
070.
int
code = connection.getResponseCode();
071.
if
(
200
== code) {
072.
inputStream = connection.getInputStream();
073.
imgBitmap = BitmapFactory.decodeStream(inputStream);
074.
}
075.
}
076.
}
catch
(Exception e) {
077.
e.printStackTrace();
078.
return
null
;
079.
}
080.
publishProgress(
100
);
//下载完成,更新进度条为满格
081.
//这里不是UI线程,故不能直接setImage(imgBitmap),
082.
return
imgBitmap;
083.
}
084.
085.
/**在调用publishProgress之后被调用,在ui线程执行 **/
086.
@Override
087.
protected
void
onProgressUpdate(Integer... values) {
088.
progressBar.setProgress(values[
0
]);
//设置进度条的进度
089.
}
090.
/**在后台线程执行完成之后,调用该方法,获取数据更新界面**/
091.
@Override
092.
protected
void
onPostExecute(Bitmap result) {
093.
if
(result !=
null
) {
094.
Toast.makeText(MainActivity.
this
,
"成功获取图片"
, Toast.LENGTH_LONG).show();
095.
imgView.setImageBitmap(result);
096.
}
else
{
097.
Toast.makeText(MainActivity.
this
,
"获取图片失败"
, Toast.LENGTH_LONG).show();
098.
}
099.
}
100.
/**取消任务,在ui线程执行 **/
101.
@Override
102.
protected
void
onCancelled() {
103.
progressBar.setProgress(
0
);
//进度条复位
104.
super
.onCancelled();
105.
}
106.
}
107.
}
分析:
1.点击按钮之后,创建一个任务,参数值为url(所以第一个参数为String)
2.UI线程执行onPreExecute(),把ImageView的图片清空,progrssbar的进度清零。
3.后台线程执行doInBackground(),不可以在doInBackground()操作ui,调用publishProgress(0)更新进度,此时会调用onProgressUpdate(Integer...progress)更新进度条(进度用整形表示,因此AsyncTask的第二个模板参数是Integer)。函数最后返回result(例子中是返回Bitmap类型,因此AsyncTask的第三个模板参数是Bitmap)。
4.当后台任务执行完成后,调用onPostExecute(Result),传入的参数是doInBackground()中返回的对象。
这篇关于Android中异步加载数据(二)AsyncTask异步更新界面的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!