Android项目实战-ListView异步图片加载及压缩缓存

这回先讲一下ListView异步加载图片的问题,相关的文章很多,不过在这里我将加载、压缩下载、存储到SD卡等功能全部放上来,方便大家使用或者研究。

 

1.      ListView中的SimpleAdapter中的操作

大家在使用ListView显示复杂的页面时,我们都全重写一个SimpleAdapter,重写其中的getView方法来显示具体内容。相关的内容我们下篇文章再说,这里主要看下图片显示的代码。

01//图片内容显示
02        if(!topic.getImage_value().equals("")){
03            vh.tl_ll_content_image.setVisibility(View.VISIBLE);
04            //加上标识,要不图片加载会变乱
05            vh.tl_img_content_image.setTag(topic.getTid());
06            vh.tl_img_content_image.setImageResource(R.drawable.default_image_load);
07            //新开异步加载图片
08            LoadingTopicImageAsyncTaskloadingTopicImageAsyncTask = new LoadingTopicImageAsyncTask(vh.tl_img_content_image, topic,ctxContext,true,String.valueOf(topic.getTid()));
09            loadingTopicImageAsyncTask.execute();
10         }

·vh. tl_ll_content_image是我们在ListView中要显示相关图片的控件。Topic是我们通过getView取到的当前行的数据对象。Topic.getImage_value()中则是要显示的图片url地址,比如:http://www.huoban168.com/huoban/upload/topic/2012/02/weibo_1329196372_1112447.png。

 ·为图片控件加上setTag主要是防止图片混乱。

·LoadingTopicImageAsyncTask是我们新开一个异步,下载或者加载相关的图片的类。基本上主要的操作都在此类中进行。

 

2.      LoadingTopicImageAsyncTask类中的操作

001packagehb.hbwb.asynctask;
002importhb.hbwb.model.beans.Topic;
003importhb.hbwb.tools.PicTool;
004importhb.hbwb.var.PublicVariable;
005  
006importandroid.app.Activity;
007importandroid.app.Dialog;
008importandroid.graphics.Bitmap;
009importandroid.os.AsyncTask;
010importandroid.view.View;
011importandroid.view.View.OnClickListener;
012importandroid.widget.ImageView;
013  
014/**
015 * @name 异步加载图片
016 * @author zhang.yue
017 * @create_date 2011-12-15
018 * @last_edit_author
019 * @last_edit_date
020 * @remark
021 * @edit_remark
022 */
023public classLoadingTopicImageAsyncTask extends
024           AsyncTask<String, Integer,String> {
025private ImageView imageView = null;
026private Topic topic = null;
027private Bitmap bt = null;
028private Activity activity;
029private boolean isClick = true;
030private String tag = "";
031  
032/**
033 * 重写构造
034 *
035 * @paramheaderView
036 *            图像控件
037 * @paramtopic
038 * @paramactivity
039 * @paramisClick
040 *            是否可以点击放大
041 */
042public LoadingTopicImageAsyncTask(ImageViewimageView, Topic topic,
043                    Activity activity, booleanisClick, String tag) {
044           super();
045           this.imageView = imageView;
046           this.topic = topic;
047           this.activity = activity;
048           this.isClick = isClick;
049           this.tag = tag;
050}
051  
052@Override
053protected String doInBackground(String...params) {
054           // 添加如果是本地缓存的从本地读取...
055           bt =PublicVariable.allTopicImage.get(String.valueOf(topic.getTid()));
056           if (bt == null) {
057                    // 图像获取并保存
058                    if (topic.getImage_value().equals("")){
059                             bt = null;
060                    } else {
061                             bt =PicTool.ReturnBitMap(topic.getImage_value());
062                    }
063           }
064           if (bt!=null) {                               
065                    if(bt.getWidth()>PublicVariable.TOPIC_IMAGE_SHOW-40 ||bt.getHeight()>PublicVariable.TOPIC_IMAGE_SHOW_HEIGHT-40) {
066                             bt =PicTool.ChangeSizeBitMap(bt, PublicVariable.TOPIC_IMAGE_SHOW-40);
067                    }
068           }
069           return null;
070}
071  
072@Override
073protected void onPostExecute(String result) {
074           super.onPostExecute(result);
075           if (imageView != null &&topic != null && !tag.equals("")) {
076                    if(imageView.getTag().toString().equals(tag)) {
077                             if (bt != null) {
078                                       if(isClick) {
079                                                //点击大图效果
080                                                imageView.setOnClickListener(newOnClickListener() {
081                                                         @Override
082                                                         publicvoid onClick(View v) {
083                                                                   ShowImageClickListener(bt,activity);
084                                                         }
085                                                });
086                                       }
087                                       imageView.setImageBitmap(bt);
088                                       PublicVariable.allTopicImage.put(
089                                                         String.valueOf(topic.getTid()),bt); // 保存到数组中
090                             }
091                    }
092           }
093}
094  
095/**
096 * 图片点击功能事件处理
097 *
098 * @parambt
099 * @paramactivity
100 */
101public static voidShowImageClickListener(Bitmap bt, Activity activity) {
102           Bitmap maxBt =PicTool.ChangeSizeBitMap(bt,
103                             PublicVariable.TOPIC_IMAGE_SHOW);
104           ImageView showImageView = newImageView(activity);
105           showImageView.setImageBitmap(maxBt);
106           //两个嵌套的TabHost中,必须使用activity.getParent()
107           //在首页中使用并无报错,全局使用
108           Dialog d = newDialog(activity.getParent(), hb.hbwb.R.style.no_back_title_dialog);
109           d.setContentView(showImageView);
110           d.setCanceledOnTouchOutside(true);
111           d.show();
112}
113  
114}

·PublicVariable.allTopicImage是我们写的一个HashMap,存储Bitmap的一个集合,如果在程序的运行过程中多次显示同一个图片即可直接从这里面取出Bitmap并显示,可以节省网上加载或者sd卡读取的步骤,键值是topic的tid,一个微博仅显示一张图片。

·如果上述的Bitmap集合中不存在图片的话,调用PicTool类中的ReturnBitMap返回SD卡上缓存的图片。

·如果图片超过我们规定的一个大小,那么调用PicTool类中的ChangeSizeBitMap方法。

·onPostExecute方法是线程执行完成后,我们将Bitmap对象给予Image图片控件并显示出来。在这里我们还添加了点击事件。

 

3.      ReturnBitMap解析

001/**
002 * 返回图片文件用
003 *
004 * @paramurl
005 *            图片url地址
006 *@return
007 */
008public static Bitmap ReturnBitMap(String url) {
009           String imgName =StringTool.GetImageNameForUrl(url);
010           if (imgName.equals("")) {
011                    return null;
012           } else {
013                    FileTool ft = newFileTool();
014                    String path =FileFinals.SDCARDROOT + File.separator + FileFinals.SDCARDIMAGEPATH;
015                    // 图片文件存在并且不是刷新的时候
016                    if (ft.IsFileExist(imgName +FileFinals.IMAGE_SYSTEM_EXT, FileFinals.SDCARDIMAGEPATH)) {
017                             Bitmap bm =ReturnLocalBitMap(path + File.separator + imgName);
018                             if(bm==null){
019                                       returnReturnWebBitMap(url, imgName, path);
020                             }else{
021                                       returnbm;
022                              }
023                    } else {
024                             // 先删除原有的
025                             returnReturnWebBitMap(url, imgName, path);
026                    }
027           }
028}
029         
030  
031/**
032 * 本地获取图片信息
033 *
034 * @parampath
035 *            图片路径
036 *@return bitmap对象
037 */
038public static Bitmap ReturnLocalBitMap(Stringpath) {
039           Bitmap bitmap =BitmapFactory.decodeFile(path + ".image");
040           return bitmap;
041}
042  
043/**
044 * 抓取远程图片
045 *
046 * @paramurl
047 *            图片地址
048 * @paramimgName
049 *            图片名
050 * @parampath
051 *            地址
052 *@return
053 */
054public static Bitmap ReturnWebBitMap(Stringurl, String imgName, String path) {
055  
056           Bitmap bitmap = null;
057           try {
058                    // 图片大小判断操作
059                    InputStream size_is =HTMLTool.GetHttpConnection(url).getInputStream();
060                    BitmapFactory.Options op =new BitmapFactory.Options();
061                    op.inJustDecodeBounds =true;
062                    @SuppressWarnings("unused")
063                    Bitmap size_bitmap =BitmapFactory.decodeStream(size_is, null, op);
064                    op.inJustDecodeBounds =true; // 仅获取宽高信息,不加载整个图片
065                    boolean isop = false;
066                    int size =PublicVariable.TOPIC_IMAGE_SHOW; // 设定获取的大小不能超过宽高
067                    int bili = 0; // 压缩比例
068                    BitmapFactory.Options op_new= new BitmapFactory.Options();
069                    if(op.outWidth>op.outHeight){
070                             if (op.outWidth> size) {
071                                       bili =op.outWidth / size;
072                                       isop =true;
073                             }
074                    }else{
075                             if (op.outHeight> size) {
076                                       bili =op.outHeight / size;
077                                         
078                                       isop =true;
079                             }
080                    }
081                    
082                    // 根据比例判断
083                    if (bili != 0) {
084                             if (bili < 2) {
085                                       bili = 2;
086                             }else{
087                                 bili = bili*2-2;
088                             }
089                             if(bili%2!=0){
090                                       bili =bili+1;
091                             }
092                             op_new.inSampleSize= bili;
093                    } else {
094                             isop = false;
095                    }
096                    System.out.println(bili);
097                    size_bitmap = null;
098                    size_is.close();
099  
100                    // 如果进行过压缩,加载处理后的图片,如果没有直接加载
101                    InputStream is =HTMLTool.GetHttpConnection(url).getInputStream();
102                    if (isop) {
103                             op_new.inPreferredConfig= Bitmap.Config.ARGB_4444;
104                             op_new.inPurgeable= true;
105                             op_new.inInputShareable= true;
106                             bitmap =BitmapFactory.decodeStream(is, null, op_new);
107                    } else {
108                             bitmap =BitmapFactory.decodeStream(is);
109                    }
110                    
111  
112                    // 将图片写入到内存卡中,做为缓存,将来直接本地读取
113                    WriteBitmapToSdCard(FileFinals.SDCARDIMAGEPATH,path + File.separator + imgName, bitmap);
114  
115                    is.close();
116  
117           } catch (Exception e) {
118                    return null;
119           }
120           return bitmap;
121}

·StringTool.GetImageNameForUrl是截取文件名,比如:http://www.huoban168.com/huoban/upload/topic/2012/02/weibo_1329196372_1112447.png,返回的是weibo_1329196372_1112447.png这一部分的内容。

·接下来查看当前SD卡的缓存文件路径下有没有这张图,如果有的话,直接调用ReturnLocalBitMap加载图片,如果没有的话,调用ReturnWebBitMap方法去调用网络图片并下载下来。

·后缀名都加了一个".image",目的是防止Android的图片浏览器去加载这些图片。

·ReturnWebBitMap中,先通过HTMLConnection获取图片的InputStream二进制流,然后通过 op.inJustDecodeBounds = true; // 这个方法,获取一个只有高度等属性的Bitmap对象,接着根据图片原始大小获取需要大小的压缩比例op_new.inSampleSize = bili;。

·最后取到压缩过的Bitmap对象写入到内存卡或者直接显示均可。至此,图片的下载和保存已完成。

 

4.      ChangeSizeBitMap解析

01/**
02          * 等比例缩放图片
03          *
04          * @param bt
05          *           bitmap图片对象
06          * @param resize
07          *           状态,是否进行缩放
08          * @return bitmap图片对象
09          */
10         publicstatic Bitmap ChangeSizeBitMap(Bitmap bt, int resize) {
11                   intsrc_width = bt.getWidth();
12                   intsrc_height = bt.getHeight();
13                   floatwidth = (float)bt.getWidth();
14                   floatheight = (float)bt.getHeight();
15                   floatbmpWidth = (float) resize / width;
16                   floatbmpHeight = (float) resize / height;
17                   if(width >= height) {
18                            if(width > resize) {
19                                     bmpWidth= (float) resize / height;
20                                     bmpHeight= bmpWidth;
21                            }                         
22                   }else{
23                            if(height > resize) {
24                                     bmpHeight= (float) resize / height;
25                                     bmpWidth= bmpHeight;
26                            }
27                   }
28  
29                   if(bmpWidth > 1 || bmpHeight > 1) {
30                            returnbt;
31                   }
32                   Matrixmatrix = new Matrix();
33                   matrix.postScale(bmpWidth,bmpHeight);
34                   BitmapresizeBmp = Bitmap.createBitmap(bt, 0, 0, src_width, src_height, matrix, true);
35                   returnresizeBmp;
36         }

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值