Android是单线程模型,耗时操作应放在非主线程中执行,故需要异步任务
AsyncTask可以使子线程中更新UI,封装、简化异步操作
构建AsyncTask子类的参数
AsyncTask<Params, Progress, Result>是一个抽象类,通常用于被继承,继承AsyncTask需要制定三个泛型参数:
Params:启动任务时输入参数的类型
Progress:后台任务执行中返回进度值的类型
Result:后台执行任务完成后返回结果的类型
构建AsyncTask子类的回调方法:
doInBackground:必须重写,异步执行后台线程将要完成的任务,其他的 方法并不是必须的
onPreExecute:执行后台耗时操作前被调用,通常用户完成一些初始化操作
onPostExecute:当doInBackground()完成后,系统会自动调用onPostExecute()方法,并将doInBackground方法返回的值传给该方法
onProgressUpdate:在doInBackground()方法中调用publishProgress()方法更新任务的执行进度后,就会触发该方法,获取进度,更新进度条
其中调用顺序是: onProExecute()-->doInBackground()-->onPostExecute()
若在doInBackground()中调用publishProgress()方法时,调用顺序是:onProExecute()-->doInBackground()-->onProgressUpdate()-->onPostExecute()
加载网络图片的实例:
异步处理-->下载图像
UI线程-->设置图像
public class ImageTest extends Activity{
private ImageView mImageView;
private ProgressBar mProgressBar;
private static String URI = "http://pic4.nipic.com/20091121/3764872_215617048242_2.jpg";
protected void onCreate(Bundle savedInstanceState){
super.onCreate(savedInstanceState);
setContentView(R.layout.image);
mImageView = (ImageView)findViewById(R.id.image);
mProgressBar = (ProgressBar)findViewById(R.id.progressbar);
new MyAsyncTask().execute(URL); //设置传递进的参数
}
class MyAsyncTask extends AsyncTask<String, void, Bitmap>{
//<url类型, 进度值类型,返回值类型>
protected void onPreExecute(){
super.onPreExecute();
mProgressBar.setVisibility(View.VISIBLE); //显示进度条
}
protected Bitmap onPostExecute(Bitmap bitmap){
super.onPostExecute(bitma);
//操作UI,设置图像
mProgressBar.setVisibility(View.GONE);
mImageView.setImageBitmap(bitmap);
}
protected Bitmap doInBackground(String... params){
String url = params[0]; //取出对应的URL
Bitmap bitmap = null;
URLConnection connection;
InputStream is;
try{
connection = new URL(url).openConnection();
is = connection.getInputStream();
BufferedInputStream bis = new BufferedInputStream(is);
Thread.sleep(3000); //为了使加载的效果更明显,人为限制一下
//通过decodeStream解析输入流
bitmap = BitmapFactory.decodeStream(bis);
is.close(); //注意关闭输入输出流
bis.close();
}catch(IOException e){
e.printStackTrace();
}catch(InterruptedException e){
e.printStackTrace();
}
//将bitmap返回
return bitmap;
}
}
}
public class ProgressBarTest extends Activity{
private ProgressBar mProgressBar;
private MyAsyncTask mTask;
protected void onCreate(Bundle savedInstanceState){
super.onCreate(savedInstanceState);
setContentView(R.layout.progressbar);
mProgressBar = (ProgressBar)findViewById(R.id.pg);
mTask = new MyAsyncTask();
mTask.execute();
}
class MyAsyncTask extends AsyncTask<Void, Integer, Void>{
protected Void doInBackground(Void... params){
//模拟进度更新
for(int i = 0; i<100;i++)
{
publishProgress(i);
try{
Thread.sleep(300);
}catch(InterruptedException){
e.printStackTrace();
}
}
return null;
}
protected void onProgressUpdate(Integer... values){
super.onProgressUpdate(values);
//获取进度更新值
mProgressBar.setProgress(values[0]);
}
}
}
//然后将此ProgressBarTest类部署至mainActivity中但是这个会出现重复进入线程时,出现”bug“,只有将前面的AsyncTask完成后才能执行当前的任务,只需将AsyncTask生命周期与Activity生命周期一致即可,
只需要在onPause()方法中加入判断:
protected void onPause(){
super.onPause();
if(mTask != null && mTask.getStatus() == AsyncTask.Status.RUNNING){
mTask.cancel(true);
//cancel()方法只是将对应的AsyncTask标记为cancel状态,并不是真的取消
//故需要在doInBackground()和onProgressUpdate()方法中加入判断语句
}
}
protected Void doInBackground(Void... params){
//模拟进度更新
for(int i = 0; i<100;i++)
{
if(isCancelled()){
break;
}
publishProgress(i);
try{
Thread.sleep(300);
}catch(InterruptedException){
e.printStackTrace();
}
}
return null;
}
protected void onProgressUpdate(Integer... values){
super.onProgressUpdate(values);
if(isCancelled()){
return;
}
//获取进度更新值
mProgressBar.setProgress(values[0]);
}使用AsyncTask注意事项:
必须在UI线程中创建AsyncTask的实例
必须在UI线程中调用AsyncTask的execute()方法
重写的四个方法是系统自动调用的,不应手动调用
每个AsyncTask只能被执行一次,多次调用将会引发异常
只有doInBackground()方法是运行在其他线程,其他方法都是运行在主线程,即其他方法都可以更新UI,而只有这个方法需要做异步处理
681

被折叠的 条评论
为什么被折叠?



