[Android] AsyncTask使用实例---加载网络图片

先上效果图。如demo_asynctask.gif

[Android] AsyncTask使用实例---加载网络图片_第1张图片

对于图片的加载效果,见链接:[Android] PorterDuff使用实例----实现新浪微博图片下载效果

本文参考链接:http://developer.android.com/reference/android/os/AsyncTask.html

AsyncTask被设计成方便编写Thread与Handler交互的辅助类,几秒钟的背景耗时操作是理想的使用场合。
AsyncTask必须被子类化才能使用,在该过程中必须设定3个构造参数:
           1.Params 往背景线程执行时的参数类型
           2.Progress 背景线程发布任务进度的参数类型
           3.Result 背景线程的运行后最后返回的结果的参数类型
如果不需要声明参数类型,可以使用"Void"进行替代。

通常子类化声明代码:

[java]  view plain copy
  1. public class DownloadImgTask extends AsyncTask<String, Float, Bitmap>  
不需要参数的声明代码:
[java]  view plain copy
  1. public class DownloadImgTask extends AsyncTask<Void, Void, Void>  

当一个AsyncTask被执行后,会有如下4个步骤:
           1.onPreExecute() 在UI线程中调用。这个步骤通常用于一些准备操作,如显示一个进度条
           2.doInBackground(Params ...) 当onPreExecute()执行完毕后,即被背景线程调用执行。这个步骤用于执行耗时的计算。方法中为不定参数,由外部调用AsyncTask.execute(Params...)时设定。本步骤运行的过程可以通过publishProgress(Progress...)发布到onProgressUpdate(Progress...)中,运行结果将return,后被传参至onPostExecute(Result)。
           3.onProgressUpdate(Progress...) 当执行publishProgress(Progress...)后在UI线程中被调用。执行的时间是不确定的。
           4.onPostExecute(Result) 在UI线程中被调用。参数为doInBackground(Params...)的运行结果。

在AsyncTask的执行过程中可以调用cancel(boolean),方法中的参数值为false时允许已经开始工作的背景线程继续工作至任务完成;为true时则强制停止。AsyncTask将不再调用onPostExecute(Result),取而代之的是调用onCancelled(Object)。为了确定当前的AsyncTask是否已经被cancelled,应该在doInBackground(Params...)方法中执行isCancelled()进行检查。


为了AsyncTask顺利工作,必须遵守线程规则:
           1.AsyncTask必须在UI线程中被调用。JELLY_BEAN版本默认已经遵守此规则。
           2.AsyncTask的实例必须在UI线程中被创建。
           3.execute(Params...)必须在UI线程中被调用。
           4.不允许手工调用以下方法:
                      onPreExecute(), onPostExecute(Result), doInBackground(Params...), onProgressUpdate(Progress...)
           5.AsyncTask的实例只能被执行一次。再次执行时将会抛出异常:
                      java.lang.IllegalStateException: Cannot execute task: the task is already running.


本文为Sodino所有,转载请注明出处:http://blog.csdn.net/sodino/article/details/7741674

Java代码贴上,XML请各位看官自行实现:

[java]  view plain copy
  1. ActAsyncTask.java  
  2.   
  3. package lab.sodino.asynctask;  
  4.   
  5. import android.app.Activity;  
  6. import android.os.Bundle;  
  7. import android.view.View;  
  8. import android.view.View.OnClickListener;  
  9.   
  10. public class ActAsyncTask extends Activity implements OnClickListener {  
  11.     private PorterDuffView pViewA, pViewB, pViewC, pViewD;  
  12.     public static final String[] STRING_ARR = {//  
  13.     "http://developer.android.com/images/home/android-jellybean.png",//  
  14.             "http://developer.android.com/images/home/design.png",//  
  15.             "http://developer.android.com/images/home/google-play.png",//  
  16.             "http://developer.android.com/images/home/google-io.png" };  
  17.   
  18.     public void onCreate(Bundle savedInstanceState) {  
  19.         super.onCreate(savedInstanceState);  
  20.         setContentView(R.layout.main);  
  21.   
  22.         pViewA = (PorterDuffView) findViewById(R.id.pViewA);  
  23.         pViewA.setOnClickListener(this);  
  24.         pViewB = (PorterDuffView) findViewById(R.id.pViewB);  
  25.         pViewB.setOnClickListener(this);  
  26.         pViewC = (PorterDuffView) findViewById(R.id.pViewC);  
  27.         pViewC.setOnClickListener(this);  
  28.         pViewD = (PorterDuffView) findViewById(R.id.pViewD);  
  29.         pViewD.setOnClickListener(this);  
  30.     }  
  31.   
  32.     public void onClick(View v) {  
  33.         if (v instanceof PorterDuffView) {  
  34.             PorterDuffView pdView = (PorterDuffView) v;  
  35.             if (pdView.isLoading() == false) {  
  36.                 DownloadImgTask task = new DownloadImgTask(pdView);  
  37.                 task.execute(STRING_ARR[pdView.getId() % STRING_ARR.length]);  
  38.                 pdView.setPorterDuffMode(true);  
  39.                 pdView.setLoading(true);  
  40.                 pdView.setProgress(0);  
  41.                 pdView.invalidate();  
  42.             }  
  43.         }  
  44.     }  
  45. }  


[java]  view plain copy
  1. DownloadImgTask.java  
  2.   
  3.   
  4. package lab.sodino.asynctask;  
  5.   
  6. import java.io.ByteArrayOutputStream;  
  7. import java.io.IOException;  
  8. import java.io.InputStream;  
  9.   
  10. import org.apache.http.Header;  
  11. import org.apache.http.HttpEntity;  
  12. import org.apache.http.HttpResponse;  
  13. import org.apache.http.client.ClientProtocolException;  
  14. import org.apache.http.client.HttpClient;  
  15. import org.apache.http.client.methods.HttpGet;  
  16. import org.apache.http.impl.client.DefaultHttpClient;  
  17. import org.apache.http.params.HttpParams;  
  18.   
  19. import android.graphics.Bitmap;  
  20. import android.graphics.BitmapFactory;  
  21. import android.os.AsyncTask;  
  22.   
  23. /** 
  24.  * @author Sodino E-mail:[email protected] 
  25.  * @version Time:2012-7-5 上午03:34:58 
  26.  */  
  27. public class DownloadImgTask extends AsyncTask<String, Float, Bitmap> {  
  28.     private PorterDuffView pdView;  
  29.   
  30.     public DownloadImgTask(PorterDuffView pdView) {  
  31.         this.pdView = pdView;  
  32.     }  
  33.   
  34.     /** 下载准备工作。在UI线程中调用。 */  
  35.     protected void onPreExecute() {  
  36.         LogOut.out(this"onPreExecute");  
  37.     }  
  38.   
  39.     /** 执行下载。在背景线程调用。 */  
  40.     protected Bitmap doInBackground(String... params) {  
  41.         LogOut.out(this"doInBackground:" + params[0]);  
  42.         HttpClient httpClient = new DefaultHttpClient();  
  43.         HttpGet httpGet = new HttpGet(params[0]);  
  44.         InputStream is = null;  
  45.         ByteArrayOutputStream baos = null;  
  46.         try {  
  47.             HttpResponse httpResponse = httpClient.execute(httpGet);  
  48.             printHttpResponse(httpResponse);  
  49.             HttpEntity httpEntity = httpResponse.getEntity();  
  50.             long length = httpEntity.getContentLength();  
  51.             LogOut.out(this"content length=" + length);  
  52.             is = httpEntity.getContent();  
  53.             if (is != null) {  
  54.                 baos = new ByteArrayOutputStream();  
  55.                 byte[] buf = new byte[128];  
  56.                 int read = -1;  
  57.                 int count = 0;  
  58.                 while ((read = is.read(buf)) != -1) {  
  59.                     baos.write(buf, 0, read);  
  60.                     count += read;  
  61.                     publishProgress(count * 1.0f / length);  
  62.                 }  
  63.                 LogOut.out(this"count=" + count + " length=" + length);  
  64.                 byte[] data = baos.toByteArray();  
  65.                 Bitmap bit = BitmapFactory.decodeByteArray(data, 0, data.length);  
  66.                 return bit;  
  67.             }  
  68.         } catch (ClientProtocolException e) {  
  69.             e.printStackTrace();  
  70.         } catch (IOException e) {  
  71.             e.printStackTrace();  
  72.         } finally {  
  73.             try {  
  74.                 if (baos != null) {  
  75.                     baos.close();  
  76.                 }  
  77.                 if (is != null) {  
  78.                     is.close();  
  79.                 }  
  80.             } catch (IOException e) {  
  81.                 e.printStackTrace();  
  82.             }  
  83.         }  
  84.         return null;  
  85.     }  
  86.   
  87.     /** 更新下载进度。在UI线程调用。onProgressUpdate */  
  88.     protected void onProgressUpdate(Float... progress) {  
  89.         // LogOut.out(this, "onProgressUpdate");  
  90.         pdView.setProgress(progress[0]);  
  91.     }  
  92.   
  93.     /** 通知下载任务完成。在UI线程调用。 */  
  94.     protected void onPostExecute(Bitmap bit) {  
  95.         LogOut.out(this"onPostExecute");  
  96.         pdView.setPorterDuffMode(false);  
  97.         pdView.setLoading(false);  
  98.         pdView.setImageBitmap(bit);  
  99.     }  
  100.   
  101.     protected void onCancelled() {  
  102.         LogOut.out(this"DownloadImgTask cancel...");  
  103.         super.onCancelled();  
  104.     }  
  105.   
  106.     private void printHttpResponse(HttpResponse httpResponse) {  
  107.         Header[] headerArr = httpResponse.getAllHeaders();  
  108.         for (int i = 0; i < headerArr.length; i++) {  
  109.             Header header = headerArr[i];  
  110.             LogOut.out(this"name[" + header.getName() + "]value[" + header.getValue() + "]");  
  111.         }  
  112.         HttpParams params = httpResponse.getParams();  
  113.         LogOut.out(this, String.valueOf(params));  
  114.         LogOut.out(this, String.valueOf(httpResponse.getLocale()));  
  115.     }  
  116. }  


[java]  view plain copy
  1. PorterDuffView.java  
  2.   
  3. package lab.sodino.asynctask;  
  4.   
  5. import java.text.DecimalFormat;  
  6.   
  7. import android.content.Context;  
  8. import android.content.res.TypedArray;  
  9. import android.graphics.Bitmap;  
  10. import android.graphics.Canvas;  
  11. import android.graphics.Paint;  
  12. import android.graphics.PorterDuff;  
  13. import android.graphics.PorterDuffXfermode;  
  14. import android.graphics.drawable.BitmapDrawable;  
  15. import android.graphics.drawable.Drawable;  
  16. import android.util.AttributeSet;  
  17. import android.widget.ImageView;  
  18.   
  19. /** 
  20.  * 自定义组件实现新浪微博的图片加载效果。<br/> 
  21.  *  
  22.  * @author Sodino E-mail:[email protected] 
  23.  * @version Time:2012-7-9 上午01:55:04 
  24.  */  
  25. public class PorterDuffView extends ImageView {  
  26.     /** 前景Bitmap高度为1像素。采用循环多次填充进度区域。 */  
  27.     public static final int FG_HEIGHT = 1;  
  28.     /** 下载进度前景色 */  
  29.     // public static final int FOREGROUND_COLOR = 0x77123456;  
  30.     public static final int FOREGROUND_COLOR = 0x77ff0000;  
  31.     /** 下载进度条的颜色。 */  
  32.     public static final int TEXT_COLOR = 0xff7fff00;  
  33.     /** 进度百分比字体大小。 */  
  34.     public static final int FONT_SIZE = 30;  
  35.     private Bitmap bitmapBg, bitmapFg;  
  36.     private Paint paint;  
  37.     /** 标识当前进度。 */  
  38.     private float progress;  
  39.     /** 标识进度图片的宽度与高度。 */  
  40.     private int width, height;  
  41.     /** 格式化输出百分比。 */  
  42.     private DecimalFormat decFormat;  
  43.     /** 进度百分比文本的锚定Y中心坐标值。 */  
  44.     private float txtBaseY;  
  45.     /** 标识是否使用PorterDuff模式重组界面。 */  
  46.     private boolean porterduffMode;  
  47.     /** 标识是否正在下载图片。 */  
  48.     private boolean loading;  
  49.   
  50.     public PorterDuffView(Context context, AttributeSet attrs) {  
  51.         super(context, attrs);  
  52.         init(context, attrs);  
  53.     }  
  54.   
  55.     /** 生成一宽与背景图片等同高为1像素的Bitmap,。 */  
  56.     private static Bitmap createForegroundBitmap(int w) {  
  57.         Bitmap bm = Bitmap.createBitmap(w, FG_HEIGHT, Bitmap.Config.ARGB_8888);  
  58.         Canvas c = new Canvas(bm);  
  59.         Paint p = new Paint(Paint.ANTI_ALIAS_FLAG);  
  60.         p.setColor(FOREGROUND_COLOR);  
  61.         c.drawRect(00, w, FG_HEIGHT, p);  
  62.         return bm;  
  63.     }  
  64.   
  65.     private void init(Context context, AttributeSet attrs) {  
  66.         if (attrs != null) {  
  67.             // //////////////////////////////////////////  
  68.             // int count = attrs.getAttributeCount();  
  69.             // for (int i = 0; i < count; i++) {  
  70.             // LogOut.out(this, "attrNameRes:" +  
  71.             // Integer.toHexString(attrs.getAttributeNameResource(i))//  
  72.             // + " attrName:" + attrs.getAttributeName(i)//  
  73.             // + " attrResValue:" + attrs.getAttributeResourceValue(i, -1)//  
  74.             // + " attrValue:" + attrs.getAttributeValue(i)//  
  75.             // );  
  76.             // }  
  77.             // //////////////////////////////////////////  
  78.   
  79.             TypedArray typedArr = context.obtainStyledAttributes(attrs, R.styleable.porterduff_PorterDuffView);  
  80.             porterduffMode = typedArr.getBoolean(R.styleable.porterduff_PorterDuffView_porterduffMode, false);  
  81.         }  
  82.         Drawable drawable = getDrawable();  
  83.         if (porterduffMode && drawable != null && drawable instanceof BitmapDrawable) {  
  84.             bitmapBg = ((BitmapDrawable) drawable).getBitmap();  
  85.             width = bitmapBg.getWidth();  
  86.             height = bitmapBg.getHeight();  
  87.             // LogOut.out(this, "width=" + width + " height=" + height);  
  88.             bitmapFg = createForegroundBitmap(width);  
  89.         } else {  
  90.             // 不符合要求,自动设置为false。  
  91.             porterduffMode = false;  
  92.         }  
  93.   
  94.         paint = new Paint();  
  95.         paint.setFilterBitmap(false);  
  96.         paint.setAntiAlias(true);  
  97.         paint.setTextSize(FONT_SIZE);  
  98.   
  99.         // 关于FontMetrics的详情介绍,可见:  
  100.         // http://xxxxxfsadf.iteye.com/blog/480454  
  101.         Paint.FontMetrics fontMetrics = paint.getFontMetrics();  
  102.         // 注意观察本输出:  
  103.         // ascent:单个字符基线以上的推荐间距,为负数  
  104.         LogOut.out(this"ascent:" + fontMetrics.ascent//  
  105.                 // descent:单个字符基线以下的推荐间距,为正数  
  106.                 + " descent:" + fontMetrics.descent //  
  107.                 // 单个字符基线以上的最大间距,为负数  
  108.                 + " top:" + fontMetrics.top //  
  109.                 // 单个字符基线以下的最大间距,为正数  
  110.                 + " bottom:" + fontMetrics.bottom//  
  111.                 // 文本行与行之间的推荐间距  
  112.                 + " leading:" + fontMetrics.leading);  
  113.         // 在此处直接计算出来,避免了在onDraw()处的重复计算  
  114.         txtBaseY = (height - fontMetrics.bottom - fontMetrics.top) / 2;  
  115.   
  116.         decFormat = new DecimalFormat("0.0%");  
  117.     }  
  118.   
  119.     public void onDraw(Canvas canvas) {  
  120.         if (porterduffMode) {  
  121.             int tmpW = (getWidth() - width) / 2, tmpH = (getHeight() - height) / 2;  
  122.             // 画出背景图  
  123.             canvas.drawBitmap(bitmapBg, tmpW, tmpH, paint);  
  124.             // 设置PorterDuff模式  
  125.             paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.DARKEN));  
  126.             // canvas.drawBitmap(bitmapFg, tmpW, tmpH - progress * height,  
  127.             // paint);  
  128.             int tH = height - (int) (progress * height);  
  129.             for (int i = 0; i < tH; i++) {  
  130.                 canvas.drawBitmap(bitmapFg, tmpW, tmpH + i, paint);  
  131.             }  
  132.   
  133.             // 立即取消xfermode  
  134.             paint.setXfermode(null);  
  135.             int oriColor = paint.getColor();  
  136.             paint.setColor(TEXT_COLOR);  
  137.             paint.setTextSize(FONT_SIZE);  
  138.             String tmp = decFormat.format(progress);  
  139.             float tmpWidth = paint.measureText(tmp);  
  140.             canvas.drawText(decFormat.format(progress), tmpW + (width - tmpWidth) / 2, tmpH + txtBaseY, paint);  
  141.             // 恢复为初始值时的颜色  
  142.             paint.setColor(oriColor);  
  143.         } else {  
  144.             LogOut.out(this"onDraw super");  
  145.             super.onDraw(canvas);  
  146.         }  
  147.     }  
  148.   
  149.     public void setProgress(float progress) {  
  150.         if (porterduffMode) {  
  151.             this.progress = progress;  
  152.             // 刷新自身。  
  153.             invalidate();  
  154.         }  
  155.     }  
  156.   
  157.     public void setBitmap(Bitmap bg) {  
  158.         if (porterduffMode) {  
  159.             bitmapBg = bg;  
  160.             width = bitmapBg.getWidth();  
  161.             height = bitmapBg.getHeight();  
  162.   
  163.             bitmapFg = createForegroundBitmap(width);  
  164.   
  165.             Paint.FontMetrics fontMetrics = paint.getFontMetrics();  
  166.             txtBaseY = (height - fontMetrics.bottom - fontMetrics.top) / 2;  
  167.               
  168.             setImageBitmap(bg);  
  169.             // 请求重新布局,将会再次调用onMeasure()  
  170.             // requestLayout();  
  171.         }  
  172.     }  
  173.   
  174.     public boolean isLoading() {  
  175.         return loading;  
  176.     }  
  177.   
  178.     public void setLoading(boolean loading) {  
  179.         this.loading = loading;  
  180.     }  
  181.   
  182.     public void setPorterDuffMode(boolean bool) {  
  183.         porterduffMode = bool;  
  184.     }  
  185. }  

你可能感兴趣的:([Android] AsyncTask使用实例---加载网络图片)