先上效果图。如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. }


更多相关文章

  1. Android 多线程----AsyncTask异步任务详解
  2. 线程中的消息机制
  3. Android的参数大致分成两块:系统服务参数和平台系统信息。
  4. WebView与Javascript交互(相互调用参数、传值)
  5. 杂谈Android线程优先级
  6. 掌握Android中的进程和线程
  7. android 线程,服务,活动
  8. Android中多线程同步问题

随机推荐

  1. TextView 点击拨打电话
  2. Android文章收藏
  3. Android复习(七)
  4. Android.os.NetworkOnMainThreadExceptio
  5. Android:Task '' not found in root proj
  6. 【实战】android获取天气情况(Json来返回
  7. Android 判断app是否在前台运行
  8. android 底部菜单写法之FragmentTabHost
  9. GreenDao
  10. Android关机AppWidget的实现