Android--多线程之AsyncTask
2013-08-20 08:03
204 查看
前言
本片博客将介绍AsyncTask的使用,之前有介绍过线程和进程。而在AsyncTask中,运行在用户界面中,执行异步操作,并且把执行结果发布在UI线程上,且也不需要处理线程和Handler。在本篇博客里,将会讲解到AsyncTask的基本介绍,以及如何使用,最后会以一个简单的Demo讲解AsyncTask的使用。
AsyncTask
AsyncTask,异步任务,可以简单进行异步操作,并把执行结果发布到UI主线程。AsyncTask是一个抽象类,它的内部其实也是结合了Thread和Handler来实现异步线程操作,但是它形成了一个通用线程框架,更清晰简单。AsyncTask应该被用于比较简短的操作(最多几秒钟)。如果需要保持长时间运行的线程,可以使用ThreadPooExecutor或者FutureTask,关于这两个类的内容,以后再介绍,本片博客主要介绍AsyncTask。
AsyncTask被定义为一个操作,运行在一个后台线程中,其结果被发布在UI线程上。它的异步工作的参数与返回值被泛型的三个参数指定:Params、Progress、Result。AsyncTask将经历4个步骤:onPreExecute、doInBackground、onProgressUpdate、onPostExecute。下面详细讲解这三个参数与四个步骤:
三个泛型参数:
Params:被发送到执行任务的参数类型。
Progress:进度的类型,发送后台的计算进度到UI线程类型。
Result:异步任务的返回结果类型。
一个异步任务将经历四个阶段:
onPreExecute():执行在UI线程上调用执行任务之前,一般用于设置任务。
doInBackground(Params...):主要是用来执行异步任务的耗时操作,可以在这个方法中通过publishProgress()方法发布进度信息,并在执行完成之后,返回执行结果。
onProgreddUpdate(Progress...):在UI线程上接受doInBackground()传递过来的进度信息,并在UI线程上展示进度信息,它执行的时机是不确定的。
onPostExecute(Result):在UI线程上操作doInBackground()执行的返回值。
上面介绍的四个步骤的示意图:
![](http://images.cnitblog.com/blog/234895/201308/17173249-33bd93b7a2094b60bbdbcd8bb65ea3f5.x-png)
AsyncTask取消任务
在程序的任何位置,都可以通过cancel(boolean)方法进行取消任务,当取消任务之后,会改变isCancelled()的返回值,使其返回true。之后会调用onCancelled(Object)方法,替代onPostExecute()得到doInBackground()的返回结果。在运行中,可以经常通过isCancelled()方法查看任务是否被取消。
AsyncTask的使用规则
使用AsyncTask必须遵循以下规则:
AsyncTask必须声明在UI线程上。
AsyncTask必须在UI线程上实例化。
必须通过execute()方法执行任务。
不可以直接调用onPreExecute()、onPostExecute(Resut)、doInBackground(Params...)、onProgressUpdate(Progress...)方法。
可以设置任务只执行一次,如果企图再次执行会报错。
示例
一个简单的示例,通过AsyncTask下载一个网络上的图片,下载的时候展示一个等待框,并显示在一个ImageView中。
实现代码:
效果展示:
![](http://images.cnitblog.com/blog/234895/201308/17175358-d912d632eeb84f6b97e7741b22292dfe.x-png)
![](http://images.cnitblog.com/blog/234895/201308/17175425-61a3d38a45b749a09a39b932dbf0525e.x-png)
![](http://images.cnitblog.com/blog/234895/201308/17175454-def0fa6958b9413893ee5d6399dd78a5.x-png)
上面的Demo并没有用到进度的信息,下面再提供一个完整的AsyncTask的Demo,同样是下载一个图片,并且展示到一个ImageView中,但是这里在下载的过程中增加一个进度条对话框,用于展示下载的进度。
实现代码:
实现效果:
![](http://images.cnitblog.com/blog/234895/201308/17175358-d912d632eeb84f6b97e7741b22292dfe.x-png)
![](http://images.cnitblog.com/blog/234895/201308/17180036-66fcac7f98094a3ca0bdbefd86a76349.x-png)
![](http://images.cnitblog.com/blog/234895/201308/17175454-def0fa6958b9413893ee5d6399dd78a5.x-png)
源码下载
本片博客将介绍AsyncTask的使用,之前有介绍过线程和进程。而在AsyncTask中,运行在用户界面中,执行异步操作,并且把执行结果发布在UI线程上,且也不需要处理线程和Handler。在本篇博客里,将会讲解到AsyncTask的基本介绍,以及如何使用,最后会以一个简单的Demo讲解AsyncTask的使用。
AsyncTask
AsyncTask,异步任务,可以简单进行异步操作,并把执行结果发布到UI主线程。AsyncTask是一个抽象类,它的内部其实也是结合了Thread和Handler来实现异步线程操作,但是它形成了一个通用线程框架,更清晰简单。AsyncTask应该被用于比较简短的操作(最多几秒钟)。如果需要保持长时间运行的线程,可以使用ThreadPooExecutor或者FutureTask,关于这两个类的内容,以后再介绍,本片博客主要介绍AsyncTask。
AsyncTask被定义为一个操作,运行在一个后台线程中,其结果被发布在UI线程上。它的异步工作的参数与返回值被泛型的三个参数指定:Params、Progress、Result。AsyncTask将经历4个步骤:onPreExecute、doInBackground、onProgressUpdate、onPostExecute。下面详细讲解这三个参数与四个步骤:
三个泛型参数:
Params:被发送到执行任务的参数类型。
Progress:进度的类型,发送后台的计算进度到UI线程类型。
Result:异步任务的返回结果类型。
一个异步任务将经历四个阶段:
onPreExecute():执行在UI线程上调用执行任务之前,一般用于设置任务。
doInBackground(Params...):主要是用来执行异步任务的耗时操作,可以在这个方法中通过publishProgress()方法发布进度信息,并在执行完成之后,返回执行结果。
onProgreddUpdate(Progress...):在UI线程上接受doInBackground()传递过来的进度信息,并在UI线程上展示进度信息,它执行的时机是不确定的。
onPostExecute(Result):在UI线程上操作doInBackground()执行的返回值。
上面介绍的四个步骤的示意图:
AsyncTask取消任务
在程序的任何位置,都可以通过cancel(boolean)方法进行取消任务,当取消任务之后,会改变isCancelled()的返回值,使其返回true。之后会调用onCancelled(Object)方法,替代onPostExecute()得到doInBackground()的返回结果。在运行中,可以经常通过isCancelled()方法查看任务是否被取消。
AsyncTask的使用规则
使用AsyncTask必须遵循以下规则:
AsyncTask必须声明在UI线程上。
AsyncTask必须在UI线程上实例化。
必须通过execute()方法执行任务。
不可以直接调用onPreExecute()、onPostExecute(Resut)、doInBackground(Params...)、onProgressUpdate(Progress...)方法。
可以设置任务只执行一次,如果企图再次执行会报错。
示例
一个简单的示例,通过AsyncTask下载一个网络上的图片,下载的时候展示一个等待框,并显示在一个ImageView中。
实现代码:
package com.bgxt.datatimepickerdemo; import org.apache.http.HttpEntity; import org.apache.http.HttpResponse; import org.apache.http.client.HttpClient; import org.apache.http.client.methods.HttpGet; import org.apache.http.impl.client.DefaultHttpClient; import org.apache.http.util.EntityUtils; import android.app.Activity; import android.app.ProgressDialog; import android.graphics.Bitmap; import android.graphics.BitmapFactory; import android.os.AsyncTask; import android.os.Bundle; import android.view.View; import android.widget.Button; import android.widget.ImageView; public class AsyncTaskActivity1 extends Activity { private Button btnDown; private ImageView ivImage; private static String image_path = "http://ww4.sinaimg.cn/bmiddle/786013a5jw1e7akotp4bcj20c80i3aao.jpg"; private ProgressDialog dialog; @Override protected void onCreate(Bundle savedInstanceState) { // TODO Auto-generated method stub super.onCreate(savedInstanceState); setContentView(R.layout.asynctask_activity); btnDown = (Button) findViewById(R.id.btnDown); ivImage = (ImageView) findViewById(R.id.ivSinaImage); // 声明一个等待框以提示用户等待 dialog=new ProgressDialog(this); dialog.setTitle("提示信息"); dialog.setMessage("正在下载,请稍后..."); btnDown.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { // 执行一个异步任务,并把图片地址以参数的形式传递进去 new MyTask().execute(image_path); } }); } // 以String类型的参数,Void表示没有进度信息,Bitmap表示异步任务返回一个位图 public class MyTask extends AsyncTask<String, Void, Bitmap> { // 表示任务执行之前的操作 @Override protected void onPreExecute() { super.onPreExecute(); //显示等待框 dialog.show(); } //主要是完成耗时操作 @Override protected Bitmap doInBackground(String... params) { HttpClient httpClient=new DefaultHttpClient(); HttpGet httpGet=new HttpGet(params[0]); Bitmap bitmap=null; try { //从网络上下载图片 HttpResponse httpResponse =httpClient.execute(httpGet); if(httpResponse.getStatusLine().getStatusCode()==200){ HttpEntity httpEntity = httpResponse.getEntity(); byte[] data=EntityUtils.toByteArray(httpEntity); bitmap=BitmapFactory.decodeByteArray(data, 0, data.length); } } catch (Exception e) { e.printStackTrace(); } return bitmap; } //完成更新UI操作 @Override protected void onPostExecute(Bitmap result) { // TODO Auto-generated method stub super.onPostExecute(result); //设置ImageView的显示图片 ivImage.setImageBitmap(result); // 销毁等待框 dialog.dismiss(); } } }
效果展示:
上面的Demo并没有用到进度的信息,下面再提供一个完整的AsyncTask的Demo,同样是下载一个图片,并且展示到一个ImageView中,但是这里在下载的过程中增加一个进度条对话框,用于展示下载的进度。
实现代码:
package com.bgxt.datatimepickerdemo; import java.io.ByteArrayOutputStream; import java.io.InputStream; import org.apache.http.HttpResponse; import org.apache.http.client.HttpClient; import org.apache.http.client.methods.HttpGet; import org.apache.http.impl.client.DefaultHttpClient; import android.app.Activity; import android.app.ProgressDialog; import android.graphics.Bitmap; import android.graphics.BitmapFactory; import android.os.AsyncTask; import android.os.Bundle; import android.view.View; import android.widget.Button; import android.widget.ImageView; public class AsyncTaskActivity2 extends Activity { private Button btnDown; private ImageView ivImage; private static String image_path = "http://ww4.sinaimg.cn/bmiddle/786013a5jw1e7akotp4bcj20c80i3aao.jpg"; private ProgressDialog dialog; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.asynctask_activity); btnDown = (Button) findViewById(R.id.btnDown); ivImage = (ImageView) findViewById(R.id.ivSinaImage); dialog = new ProgressDialog(this); dialog.setTitle("提示"); dialog.setMessage("正在下载,请稍后..."); dialog.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL); dialog.setCancelable(false); btnDown.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { // 执行异步任务 new MyTask().execute(image_path); } }); } public class MyTask extends AsyncTask<String, Integer, Bitmap> { @Override protected void onPreExecute() { super.onPreExecute(); dialog.show(); } @Override protected void onProgressUpdate(Integer... values) { super.onProgressUpdate(values); // 设置进度对话框的进度值 dialog.setProgress(values[0]); } @Override protected void onPostExecute(Bitmap result) { super.onPostExecute(result); dialog.dismiss(); ivImage.setImageBitmap(result); } @Override protected Bitmap doInBackground(String... params) { Bitmap bitmap = null; ByteArrayOutputStream outputStream = new ByteArrayOutputStream(); InputStream inputStream = null; try { HttpClient httpClient = new DefaultHttpClient(); HttpGet httpGet = new HttpGet(params[0]); HttpResponse httpResponse = httpClient.execute(httpGet); if (httpResponse.getStatusLine().getStatusCode() == 200) { inputStream = httpResponse.getEntity().getContent(); long file_length = httpResponse.getEntity() .getContentLength(); int len = 0; byte[] data = new byte[1024]; int total_length = 0; // 以字节的方式读取图片数据 while ((len = inputStream.read(data)) != -1) { total_length += len; // 计算进度 int values = (int) ((total_length / (float) file_length) * 100); // 发布进度信息 publishProgress(values); outputStream.write(data, 0, len); } byte[] result=outputStream.toByteArray(); bitmap=BitmapFactory.decodeByteArray(result, 0, result.length); } } catch (Exception e) { e.printStackTrace(); } finally { try { if (inputStream != null) { inputStream.close(); } } catch (Exception e2) { } } return bitmap; } } }
实现效果:
源码下载
相关文章推荐
- android多线程学习---AsyncTask分析
- Android多线程任务优化1:探讨AsyncTask的缺陷
- Android 多线程-----AsyncTask详解
- Android--多线程之AsyncTask
- Android 多线程-----AsyncTask详解
- Android 多线程-----AsyncTask详解
- Android 多线程 AsyncTask的用法
- Android 多线程-----AsyncTask详解
- 浅谈Android多线程之AsyncTask
- android多线程编程之AsyncTask与Handler
- Android多线程任务优化1:探讨AsyncTask的缺陷
- Android中用AsyncTask简单实现多线程
- Android多线程,异步消息处理机制, Thread, AsyncTask 简单总结
- Android——多线程(AsyncTask封装)
- Android--多线程之AsyncTask
- Android 多线程工具Handler、AsyncTask总结
- Android AsyncTask 原理及Java多线程探索
- Android - 多线程 - AsyncTask
- Android 多线程-----AsyncTask详解
- Android 多线程-----AsyncTask详解