http://blog.csdn.net/sodino/article/details/7741674

先上效果图。如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. publicclassDownloadImgTaskextendsAsyncTask<String,Float,Bitmap>
不需要参数的声明代码:
[java] view plain copy
  1. publicclassDownloadImgTaskextendsAsyncTask<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. packagelab.sodino.asynctask;
  3. importandroid.app.Activity;
  4. importandroid.os.Bundle;
  5. importandroid.view.View;
  6. importandroid.view.View.OnClickListener;
  7. publicclassActAsyncTaskextendsActivityimplementsOnClickListener{
  8. privatePorterDuffViewpViewA,pViewB,pViewC,pViewD;
  9. publicstaticfinalString[]STRING_ARR={//
  10. "http://developer.android.com/images/home/android-jellybean.png",//
  11. "http://developer.android.com/images/home/design.png",//
  12. "http://developer.android.com/images/home/google-play.png",//
  13. "http://developer.android.com/images/home/google-io.png"};
  14. publicvoidonCreate(BundlesavedInstanceState){
  15. super.onCreate(savedInstanceState);
  16. setContentView(R.layout.main);
  17. pViewA=(PorterDuffView)findViewById(R.id.pViewA);
  18. pViewA.setOnClickListener(this);
  19. pViewB=(PorterDuffView)findViewById(R.id.pViewB);
  20. pViewB.setOnClickListener(this);
  21. pViewC=(PorterDuffView)findViewById(R.id.pViewC);
  22. pViewC.setOnClickListener(this);
  23. pViewD=(PorterDuffView)findViewById(R.id.pViewD);
  24. pViewD.setOnClickListener(this);
  25. }
  26. publicvoidonClick(Viewv){
  27. if(vinstanceofPorterDuffView){
  28. PorterDuffViewpdView=(PorterDuffView)v;
  29. if(pdView.isLoading()==false){
  30. DownloadImgTasktask=newDownloadImgTask(pdView);
  31. task.execute(STRING_ARR[pdView.getId()%STRING_ARR.length]);
  32. pdView.setPorterDuffMode(true);
  33. pdView.setLoading(true);
  34. pdView.setProgress(0);
  35. pdView.invalidate();
  36. }
  37. }
  38. }
  39. }


[java] view plain copy
  1. DownloadImgTask.java
  2. packagelab.sodino.asynctask;
  3. importjava.io.ByteArrayOutputStream;
  4. importjava.io.IOException;
  5. importjava.io.InputStream;
  6. importorg.apache.http.Header;
  7. importorg.apache.http.HttpEntity;
  8. importorg.apache.http.HttpResponse;
  9. importorg.apache.http.client.ClientProtocolException;
  10. importorg.apache.http.client.HttpClient;
  11. importorg.apache.http.client.methods.HttpGet;
  12. importorg.apache.http.impl.client.DefaultHttpClient;
  13. importorg.apache.http.params.HttpParams;
  14. importandroid.graphics.Bitmap;
  15. importandroid.graphics.BitmapFactory;
  16. importandroid.os.AsyncTask;
  17. /**
  18. *@authorSodinoE-mail:sodinoopen@hotmail.com
  19. *@versionTime:2012-7-5上午03:34:58
  20. */
  21. publicclassDownloadImgTaskextendsAsyncTask<String,Float,Bitmap>{
  22. privatePorterDuffViewpdView;
  23. publicDownloadImgTask(PorterDuffViewpdView){
  24. this.pdView=pdView;
  25. }
  26. /**下载准备工作。在UI线程中调用。*/
  27. protectedvoidonPreExecute(){
  28. LogOut.out(this,"onPreExecute");
  29. }
  30. /**执行下载。在背景线程调用。*/
  31. protectedBitmapdoInBackground(String...params){
  32. LogOut.out(this,"doInBackground:"+params[0]);
  33. HttpClienthttpClient=newDefaultHttpClient();
  34. HttpGethttpGet=newHttpGet(params[0]);
  35. InputStreamis=null;
  36. ByteArrayOutputStreambaos=null;
  37. try{
  38. HttpResponsehttpResponse=httpClient.execute(httpGet);
  39. printHttpResponse(httpResponse);
  40. HttpEntityhttpEntity=httpResponse.getEntity();
  41. longlength=httpEntity.getContentLength();
  42. LogOut.out(this,"contentlength="+length);
  43. is=httpEntity.getContent();
  44. if(is!=null){
  45. baos=newByteArrayOutputStream();
  46. byte[]buf=newbyte[128];
  47. intread=-1;
  48. intcount=0;
  49. while((read=is.read(buf))!=-1){
  50. baos.write(buf,0,read);
  51. count+=read;
  52. publishProgress(count*1.0f/length);
  53. }
  54. LogOut.out(this,"count="+count+"length="+length);
  55. byte[]data=baos.toByteArray();
  56. Bitmapbit=BitmapFactory.decodeByteArray(data,0,data.length);
  57. returnbit;
  58. }
  59. }catch(ClientProtocolExceptione){
  60. e.printStackTrace();
  61. }catch(IOExceptione){
  62. e.printStackTrace();
  63. }finally{
  64. try{
  65. if(baos!=null){
  66. baos.close();
  67. }
  68. if(is!=null){
  69. is.close();
  70. }
  71. }catch(IOExceptione){
  72. e.printStackTrace();
  73. }
  74. }
  75. returnnull;
  76. }
  77. /**更新下载进度。在UI线程调用。onProgressUpdate*/
  78. protectedvoidonProgressUpdate(Float...progress){
  79. //LogOut.out(this,"onProgressUpdate");
  80. pdView.setProgress(progress[0]);
  81. }
  82. /**通知下载任务完成。在UI线程调用。*/
  83. protectedvoidonPostExecute(Bitmapbit){
  84. LogOut.out(this,"onPostExecute");
  85. pdView.setPorterDuffMode(false);
  86. pdView.setLoading(false);
  87. pdView.setImageBitmap(bit);
  88. }
  89. protectedvoidonCancelled(){
  90. LogOut.out(this,"DownloadImgTaskcancel...");
  91. super.onCancelled();
  92. }
  93. privatevoidprintHttpResponse(HttpResponsehttpResponse){
  94. Header[]headerArr=httpResponse.getAllHeaders();
  95. for(inti=0;i<headerArr.length;i++){
  96. Headerheader=headerArr[i];
  97. LogOut.out(this,"name["+header.getName()+"]value["+header.getValue()+"]");
  98. }
  99. HttpParamsparams=httpResponse.getParams();
  100. LogOut.out(this,String.valueOf(params));
  101. LogOut.out(this,String.valueOf(httpResponse.getLocale()));
  102. }
  103. }


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



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

更多相关文章

  1. Android之进度条
  2. ProgressBar进度条
  3. FregServer进程,发送BC_TRANSACTION,唤醒ServiceManager进程,返回BR
  4. 在非主线程中不能操作主线程中的View
  5. Android 中带有进度条效果的按钮(Button)
  6. Android 获取系统设置参数。
  7. Android 学习笔记 Contacts (一)ContentResolver query 参数详解
  8. Android notification点击跳转到Activity,点击返回跳转,前一条消息
  9. Android Material Design 进度条 自定义进度条样式

随机推荐

  1. Android(安卓)Studio 从安装到配置使用
  2. Android之NDK开发详解
  3. android 事件分发机制(源码解析)
  4. Android中数据存储——SharedPreferences
  5. Android程序开发初级教程(一) 开始 Hello
  6. Android关于No Activity found to handle
  7. Android的进程和线程
  8. Mac下搭建Android开发环境
  9. Android界面设计简单讲解
  10. android之声音管理器AudioManager的使用