[置顶] [Android] AsyncTask使用实例---加载网络图片
16lz
2021-12-04
http://blog.csdn.net/sodino/article/details/7741674
先上效果图。如demo_asynctask.gif
对于图片的加载效果,见链接:[Android] PorterDuff使用实例----实现新浪微博图片下载效果
本文参考链接:http://developer.android.com/reference/android/os/AsyncTask.html
AsyncTask被设计成方便编写Thread与Handler交互的辅助类,几秒钟的背景耗时操作是理想的使用场合。
AsyncTask必须被子类化才能使用,在该过程中必须设定3个构造参数:
1.Params 往背景线程执行时的参数类型
2.Progress 背景线程发布任务进度的参数类型
3.Result 背景线程的运行后最后返回的结果的参数类型
如果不需要声明参数类型,可以使用"Void"进行替代。
通常子类化声明代码:
- publicclassDownloadImgTaskextendsAsyncTask<String,Float,Bitmap>
[java] view plain copy
- 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- ActAsyncTask.java
- packagelab.sodino.asynctask;
- importandroid.app.Activity;
- importandroid.os.Bundle;
- importandroid.view.View;
- importandroid.view.View.OnClickListener;
- publicclassActAsyncTaskextendsActivityimplementsOnClickListener{
- privatePorterDuffViewpViewA,pViewB,pViewC,pViewD;
- publicstaticfinalString[]STRING_ARR={//
- "http://developer.android.com/images/home/android-jellybean.png",//
- "http://developer.android.com/images/home/design.png",//
- "http://developer.android.com/images/home/google-play.png",//
- "http://developer.android.com/images/home/google-io.png"};
- publicvoidonCreate(BundlesavedInstanceState){
- super.onCreate(savedInstanceState);
- setContentView(R.layout.main);
- pViewA=(PorterDuffView)findViewById(R.id.pViewA);
- pViewA.setOnClickListener(this);
- pViewB=(PorterDuffView)findViewById(R.id.pViewB);
- pViewB.setOnClickListener(this);
- pViewC=(PorterDuffView)findViewById(R.id.pViewC);
- pViewC.setOnClickListener(this);
- pViewD=(PorterDuffView)findViewById(R.id.pViewD);
- pViewD.setOnClickListener(this);
- }
- publicvoidonClick(Viewv){
- if(vinstanceofPorterDuffView){
- PorterDuffViewpdView=(PorterDuffView)v;
- if(pdView.isLoading()==false){
- DownloadImgTasktask=newDownloadImgTask(pdView);
- task.execute(STRING_ARR[pdView.getId()%STRING_ARR.length]);
- pdView.setPorterDuffMode(true);
- pdView.setLoading(true);
- pdView.setProgress(0);
- pdView.invalidate();
- }
- }
- }
- }
[java] view plain copy
- DownloadImgTask.java
- packagelab.sodino.asynctask;
- importjava.io.ByteArrayOutputStream;
- importjava.io.IOException;
- importjava.io.InputStream;
- importorg.apache.http.Header;
- importorg.apache.http.HttpEntity;
- importorg.apache.http.HttpResponse;
- importorg.apache.http.client.ClientProtocolException;
- importorg.apache.http.client.HttpClient;
- importorg.apache.http.client.methods.HttpGet;
- importorg.apache.http.impl.client.DefaultHttpClient;
- importorg.apache.http.params.HttpParams;
- importandroid.graphics.Bitmap;
- importandroid.graphics.BitmapFactory;
- importandroid.os.AsyncTask;
- /**
- *@authorSodinoE-mail:sodinoopen@hotmail.com
- *@versionTime:2012-7-5上午03:34:58
- */
- publicclassDownloadImgTaskextendsAsyncTask<String,Float,Bitmap>{
- privatePorterDuffViewpdView;
- publicDownloadImgTask(PorterDuffViewpdView){
- this.pdView=pdView;
- }
- /**下载准备工作。在UI线程中调用。*/
- protectedvoidonPreExecute(){
- LogOut.out(this,"onPreExecute");
- }
- /**执行下载。在背景线程调用。*/
- protectedBitmapdoInBackground(String...params){
- LogOut.out(this,"doInBackground:"+params[0]);
- HttpClienthttpClient=newDefaultHttpClient();
- HttpGethttpGet=newHttpGet(params[0]);
- InputStreamis=null;
- ByteArrayOutputStreambaos=null;
- try{
- HttpResponsehttpResponse=httpClient.execute(httpGet);
- printHttpResponse(httpResponse);
- HttpEntityhttpEntity=httpResponse.getEntity();
- longlength=httpEntity.getContentLength();
- LogOut.out(this,"contentlength="+length);
- is=httpEntity.getContent();
- if(is!=null){
- baos=newByteArrayOutputStream();
- byte[]buf=newbyte[128];
- intread=-1;
- intcount=0;
- while((read=is.read(buf))!=-1){
- baos.write(buf,0,read);
- count+=read;
- publishProgress(count*1.0f/length);
- }
- LogOut.out(this,"count="+count+"length="+length);
- byte[]data=baos.toByteArray();
- Bitmapbit=BitmapFactory.decodeByteArray(data,0,data.length);
- returnbit;
- }
- }catch(ClientProtocolExceptione){
- e.printStackTrace();
- }catch(IOExceptione){
- e.printStackTrace();
- }finally{
- try{
- if(baos!=null){
- baos.close();
- }
- if(is!=null){
- is.close();
- }
- }catch(IOExceptione){
- e.printStackTrace();
- }
- }
- returnnull;
- }
- /**更新下载进度。在UI线程调用。onProgressUpdate*/
- protectedvoidonProgressUpdate(Float...progress){
- //LogOut.out(this,"onProgressUpdate");
- pdView.setProgress(progress[0]);
- }
- /**通知下载任务完成。在UI线程调用。*/
- protectedvoidonPostExecute(Bitmapbit){
- LogOut.out(this,"onPostExecute");
- pdView.setPorterDuffMode(false);
- pdView.setLoading(false);
- pdView.setImageBitmap(bit);
- }
- protectedvoidonCancelled(){
- LogOut.out(this,"DownloadImgTaskcancel...");
- super.onCancelled();
- }
- privatevoidprintHttpResponse(HttpResponsehttpResponse){
- Header[]headerArr=httpResponse.getAllHeaders();
- for(inti=0;i<headerArr.length;i++){
- Headerheader=headerArr[i];
- LogOut.out(this,"name["+header.getName()+"]value["+header.getValue()+"]");
- }
- HttpParamsparams=httpResponse.getParams();
- LogOut.out(this,String.valueOf(params));
- LogOut.out(this,String.valueOf(httpResponse.getLocale()));
- }
- }
[java] view plain copy
- PorterDuffView.java
- packagelab.sodino.asynctask;
- importjava.text.DecimalFormat;
- importandroid.content.Context;
- importandroid.content.res.TypedArray;
- importandroid.graphics.Bitmap;
- importandroid.graphics.Canvas;
- importandroid.graphics.Paint;
- importandroid.graphics.PorterDuff;
- importandroid.graphics.PorterDuffXfermode;
- importandroid.graphics.drawable.BitmapDrawable;
- importandroid.graphics.drawable.Drawable;
- importandroid.util.AttributeSet;
- importandroid.widget.ImageView;
- /**
- *自定义组件实现新浪微博的图片加载效果。<br/>
- *
- *@authorSodinoE-mail:sodinoopen@hotmail.com
- *@versionTime:2012-7-9上午01:55:04
- */
- publicclassPorterDuffViewextendsImageView{
- /**前景Bitmap高度为1像素。采用循环多次填充进度区域。*/
- publicstaticfinalintFG_HEIGHT=1;
- /**下载进度前景色*/
- //publicstaticfinalintFOREGROUND_COLOR=0x77123456;
- publicstaticfinalintFOREGROUND_COLOR=0x77ff0000;
- /**下载进度条的颜色。*/
- publicstaticfinalintTEXT_COLOR=0xff7fff00;
- /**进度百分比字体大小。*/
- publicstaticfinalintFONT_SIZE=30;
- privateBitmapbitmapBg,bitmapFg;
- privatePaintpaint;
- /**标识当前进度。*/
- privatefloatprogress;
- /**标识进度图片的宽度与高度。*/
- privateintwidth,height;
- /**格式化输出百分比。*/
- privateDecimalFormatdecFormat;
- /**进度百分比文本的锚定Y中心坐标值。*/
- privatefloattxtBaseY;
- /**标识是否使用PorterDuff模式重组界面。*/
- privatebooleanporterduffMode;
- /**标识是否正在下载图片。*/
- privatebooleanloading;
- publicPorterDuffView(Contextcontext,AttributeSetattrs){
- super(context,attrs);
- init(context,attrs);
- }
- /**生成一宽与背景图片等同高为1像素的Bitmap,。*/
- privatestaticBitmapcreateForegroundBitmap(intw){
- Bitmapbm=Bitmap.createBitmap(w,FG_HEIGHT,Bitmap.Config.ARGB_8888);
- Canvasc=newCanvas(bm);
- Paintp=newPaint(Paint.ANTI_ALIAS_FLAG);
- p.setColor(FOREGROUND_COLOR);
- c.drawRect(0,0,w,FG_HEIGHT,p);
- returnbm;
- }
- privatevoidinit(Contextcontext,AttributeSetattrs){
- if(attrs!=null){
- ////////////////////////////////////////////
- //intcount=attrs.getAttributeCount();
- //for(inti=0;i<count;i++){
- //LogOut.out(this,"attrNameRes:"+
- //Integer.toHexString(attrs.getAttributeNameResource(i))//
- //+"attrName:"+attrs.getAttributeName(i)//
- //+"attrResValue:"+attrs.getAttributeResourceValue(i,-1)//
- //+"attrValue:"+attrs.getAttributeValue(i)//
- //);
- //}
- ////////////////////////////////////////////
- TypedArraytypedArr=context.obtainStyledAttributes(attrs,R.styleable.porterduff_PorterDuffView);
- porterduffMode=typedArr.getBoolean(R.styleable.porterduff_PorterDuffView_porterduffMode,false);
- }
- Drawabledrawable=getDrawable();
- if(porterduffMode&&drawable!=null&&drawableinstanceofBitmapDrawable){
- bitmapBg=((BitmapDrawable)drawable).getBitmap();
- width=bitmapBg.getWidth();
- height=bitmapBg.getHeight();
- //LogOut.out(this,"width="+width+"height="+height);
- bitmapFg=createForegroundBitmap(width);
- }else{
- //不符合要求,自动设置为false。
- porterduffMode=false;
- }
- paint=newPaint();
- paint.setFilterBitmap(false);
- paint.setAntiAlias(true);
- paint.setTextSize(FONT_SIZE);
- //关于FontMetrics的详情介绍,可见:
- //http://xxxxxfsadf.iteye.com/blog/480454
- Paint.FontMetricsfontMetrics=paint.getFontMetrics();
- //注意观察本输出:
- //ascent:单个字符基线以上的推荐间距,为负数
- LogOut.out(this,"ascent:"+fontMetrics.ascent//
- //descent:单个字符基线以下的推荐间距,为正数
- +"descent:"+fontMetrics.descent//
- //单个字符基线以上的最大间距,为负数
- +"top:"+fontMetrics.top//
- //单个字符基线以下的最大间距,为正数
- +"bottom:"+fontMetrics.bottom//
- //文本行与行之间的推荐间距
- +"leading:"+fontMetrics.leading);
- //在此处直接计算出来,避免了在onDraw()处的重复计算
- txtBaseY=(height-fontMetrics.bottom-fontMetrics.top)/2;
- decFormat=newDecimalFormat("0.0%");
- }
- publicvoidonDraw(Canvascanvas){
- if(porterduffMode){
- inttmpW=(getWidth()-width)/2,tmpH=(getHeight()-height)/2;
- //画出背景图
- canvas.drawBitmap(bitmapBg,tmpW,tmpH,paint);
- //设置PorterDuff模式
- paint.setXfermode(newPorterDuffXfermode(PorterDuff.Mode.DARKEN));
- //canvas.drawBitmap(bitmapFg,tmpW,tmpH-progress*height,
- //paint);
- inttH=height-(int)(progress*height);
- for(inti=0;i<tH;i++){
- canvas.drawBitmap(bitmapFg,tmpW,tmpH+i,paint);
- }
- //立即取消xfermode
- paint.setXfermode(null);
- intoriColor=paint.getColor();
- paint.setColor(TEXT_COLOR);
- paint.setTextSize(FONT_SIZE);
- Stringtmp=decFormat.format(progress);
- floattmpWidth=paint.measureText(tmp);
- canvas.drawText(decFormat.format(progress),tmpW+(width-tmpWidth)/2,tmpH+txtBaseY,paint);
- //恢复为初始值时的颜色
- paint.setColor(oriColor);
- }else{
- LogOut.out(this,"onDrawsuper");
- super.onDraw(canvas);
- }
- }
- publicvoidsetProgress(floatprogress){
- if(porterduffMode){
- this.progress=progress;
- //刷新自身。
- invalidate();
- }
- }
- publicvoidsetBitmap(Bitmapbg){
- if(porterduffMode){
- bitmapBg=bg;
- width=bitmapBg.getWidth();
- height=bitmapBg.getHeight();
- bitmapFg=createForegroundBitmap(width);
- Paint.FontMetricsfontMetrics=paint.getFontMetrics();
- txtBaseY=(height-fontMetrics.bottom-fontMetrics.top)/2;
- setImageBitmap(bg);
- //请求重新布局,将会再次调用onMeasure()
- //requestLayout();
- }
- }
- publicbooleanisLoading(){
- returnloading;
- }
- publicvoidsetLoading(booleanloading){
- this.loading=loading;
- }
- publicvoidsetPorterDuffMode(booleanbool){
- porterduffMode=bool;
- }
- }
更多相关文章
- Android(安卓)剪切板监听
- android 竖屏activity跳转横屏activity返回时数据消失
- Android(安卓)获取网络状态及调用网络配置界面(转帖)
- Android(安卓)GPS学习 (一) :GPS 启动流程
- Android上调用google map api v2
- android 使用gdb调试的方式
- 浅析android下如何通过jni监控wifi网络连接、dhcpcd执行和power
- Android上传文件到Web服务器,PHP接收文件(二)
- Android之Input子系统事件分发流程