网络图片加载优化(一)利用弱引用缓存异步加载

 

【Android】网络图片加载优化(一)利用弱引用缓存异步加载

分类: Android开发   581人阅读  评论(2)  收藏  举报
android 异步 缓存 图片 优化

目录(?)[+]

应用背景

ListView 或GridView是一种可以显示一系列项目并能进行滚动显示的 View,每一行的Item可能包含复杂的结构。

其可能会从网络上获取一些图片信息,就现在的网络速度要想保持ListView运行的很好滚动流畅是做不到的。

所以这里就需要把这些信息利用多线程实现异步加载,同时,应用弱引用缓存技术方便再次加载时预览。

工作原理

使用了SoftReference来缓存图片,允许 GC在需要的时候可以对缓存中的图片进行清理。

它是这样工作:

(1) 调用 loadDrawable(ImageUrl, imageCallback),传入一个匿名实现的 ImageCallback接口;

(2)如果图片在缓存中不存在的话,图片将从单一的线程中下载并在下载结束时通过 ImageCallback回调;

(3)如果图片确实存在于缓存中,就会马上返回,不会回调 ImageCallback。

弱应用缓存类的封装

[java]  view plain copy
  1. package com.wei.util;  
  2.   
  3. import java.lang.ref.SoftReference;  
  4. import java.net.URL;  
  5. import java.util.HashMap;  
  6. import android.graphics.Bitmap;  
  7. import android.graphics.BitmapFactory;  
  8. import android.os.Handler;  
  9. import android.os.Message;  
  10.   
  11.   
  12. public class AsyncImageLoader{  
  13.     Bitmap bitmap = null;  
  14.     HashMap<String, SoftReference<Bitmap>> imageCache;  
  15.     BitmapFactory.Options opts;  
  16.     // 1.根据URL返回Drawable的函数  
  17.     // 2.工具类的核心函数,包含handler+thread  
  18.   
  19.     public AsyncImageLoader() {  
  20.         imageCache = new HashMap<String, SoftReference<Bitmap>>();  
  21.         opts = new BitmapFactory.Options();     
  22.         opts.inSampleSize = 0;    //这个的值压缩的倍数(2的整数倍),数值越小,压缩率越小,图片越清晰      
  23.     }  
  24.   
  25.     public Bitmap asyncLoadImage(final String strUrl, final int i, final LoadFinishCallBack loadFinishCallBack) {  
  26.         Bitmap bitmap = null;  
  27.         //首先判断Map中是否有这种图片的缓存,若有,直接返回该图片的引用  
  28.         if(imageCache.containsKey(strUrl)) {  
  29.             SoftReference<Bitmap> softReference = imageCache.get(strUrl);  
  30.             bitmap = softReference.get();  
  31.             if(bitmap != null) {  
  32.                 return bitmap;  
  33.             }  
  34.         }  
  35.           
  36.         final Handler handler = new Handler() {  
  37.             @Override  
  38.             public void handleMessage(Message msg) {  
  39.                 // 回调接口  
  40.                 loadFinishCallBack.loadFinish(strUrl, i, (Bitmap) msg.obj);  
  41.             }  
  42.         };  
  43.   
  44.         new Thread() {  
  45.             @Override  
  46.             public void run() {  
  47.                 Bitmap bitmap = null;  
  48.                 try {  
  49.                     bitmap = BitmapFactory.decodeStream(new URL(strUrl).openConnection().getInputStream(), null, opts);   
  50.                 } catch (Exception e) {  
  51.                     e.printStackTrace();  
  52.                 }  
  53.                 imageCache.put(strUrl, new SoftReference<Bitmap>(bitmap));//第一次拿某张图片,把该图片的引用放入缓存中  
  54.                 Message msg = new Message();  
  55.                 msg.obj = bitmap;  
  56.                 //System.out.println("bitmap 宽高"+bitmap.getWidth()+"-"+bitmap.getHeight());  
  57.                 handler.sendMessage(msg);  
  58.             }  
  59.         }.start();  
  60.   
  61.         return bitmap;  
  62.     }  
  63.   
  64.     public interface LoadFinishCallBack {  
  65.         public void loadFinish(String strUrl, int i, Bitmap bitmap);  
  66.     }  
  67. }  

弱引用缓存类的应用

[java]  view plain copy
  1. Bitmap bm = asyncImageLoader.asyncLoadImage(strUrl, 0, callback);  
  2. oneView.image.setImageBitmap(null);  
  3. if(bm==null) {  
  4.     oneView.image.setBackgroundResource(R.drawable.slt);  
  5. else {  
  6.     oneView.image.setImageBitmap(bm);  
  7. }  
其中,asyncImageLoader是上述封装类的实例,R.drawable.slt是图片未加载出来时显示的图片资源。
callback是所调用的接口:
[java]  view plain copy
  1. //图片下载成功后执行的回调接口  
  2. LoadFinishCallBack callback = new LoadFinishCallBack() {  
  3.     @Override  
  4.     public void loadFinish(String strUrl, int i, Bitmap bitmap) {  
  5.         if (bitmap != null) {  
  6.             ImageView imageView = (ImageView) gridView.findViewWithTag(strUrl);  
  7.             if(imageView != null) {  
  8.                 imageView.setImageBitmap(bitmap);  
  9.             }  
  10.         }  
  11.     };  
  12. };  

应用举例

[java]  view plain copy
  1. package com.wei.adapter;  
  2.   
  3. import java.io.IOException;  
  4. import java.io.InputStream;  
  5. import java.net.HttpURLConnection;  
  6. import java.net.URL;  
  7. import java.net.URLConnection;  
  8.   
  9. import org.json.JSONArray;  
  10. import org.json.JSONException;  
  11. import org.json.JSONObject;  
  12.   
  13. import com.wei.util.AsyncImageLoader;  
  14. import com.wei.util.MyApplication;  
  15. import com.wei.util.MyImgCache;  
  16. import com.wei.util.MyThread;  
  17. import com.wei.util.AsyncImageLoader.LoadFinishCallBack;  
  18. import com.wei.wotao.FavorActivity;  
  19. import com.wei.wotao.R;  
  20. import com.wei.wotao.WebViewActivity;  
  21.   
  22.   
  23. import android.R.integer;  
  24. import android.app.Application;  
  25. import android.content.Context;  
  26. import android.content.Intent;  
  27. import android.content.SharedPreferences;  
  28. import android.graphics.Bitmap;  
  29. import android.graphics.Paint;  
  30. import android.graphics.drawable.Drawable;  
  31. import android.os.Handler;  
  32. import android.view.LayoutInflater;  
  33. import android.view.View;  
  34. import android.view.ViewGroup;  
  35. import android.view.ViewGroup.LayoutParams;  
  36. import android.widget.BaseAdapter;  
  37. import android.widget.Button;  
  38. import android.widget.GridView;  
  39. import android.widget.ImageView;  
  40. import android.widget.TextView;  
  41. import android.widget.Toast;  
  42.   
  43.   
  44. public class FavorAdapter extends BaseAdapter{  
  45.     private LayoutInflater mInflater;// 动态布局映射  
  46.     private JSONArray list;  
  47.     private Context context;   
  48.     GridView gridView;  
  49.     private int i = 0;  
  50.     AsyncImageLoader asyncImageLoader;  
  51.     int itemWidth;  
  52.     private String nickname;  
  53.     public FavorAdapter(JSONArray list,GridView gridView,Context context,String nickname){  
  54.         this.list = list;  
  55.         this.context = context;  
  56.         this.gridView = gridView;  
  57.         this.mInflater = LayoutInflater.from(context);  
  58.         itemWidth = MyApplication.screenWidth/2;  
  59.         asyncImageLoader  = new AsyncImageLoader();  
  60.         this.nickname = nickname;  
  61. //      SharedPreferences share = getSharedPreferences("logInfo", 2);  
  62. //      nickname = share.getString("username", "");  
  63.     }  
  64.     public void setList(JSONArray list) {  
  65.         this.list = list;  
  66.     }  
  67.     public JSONArray getList() {  
  68.         return list;  
  69.     }  
  70.     @Override  
  71.     public int getCount() {  
  72.         // TODO Auto-generated method stub  
  73.         return list.length();  
  74.     }  
  75.   
  76.     @Override  
  77.     public Object getItem(int position) {  
  78.         // TODO Auto-generated method stub  
  79.         return null;  
  80.     }  
  81.   
  82.     @Override  
  83.     public long getItemId(int position) {  
  84.         // TODO Auto-generated method stub  
  85.         return 0;  
  86.     }  
  87.     @Override  
  88.     public View getView(int position, View convertView, ViewGroup parent) {  
  89.         // TODO Auto-generated method stub  
  90.         OneView oneView;  
  91.         if (convertView == null) {  
  92.             convertView = mInflater.inflate(R.layout.subitem_item_grid_favor2, null);//根据布局文件实例化view  
  93.             oneView = new OneView();  
  94.             oneView.promotion_price = (TextView) convertView.findViewById(R.id.promotion_price);//找某个控件  
  95.             oneView.price = (TextView) convertView.findViewById(R.id.price);  
  96.             oneView.sub_price = (TextView) convertView.findViewById(R.id.sub_price);  
  97.             oneView.image = (ImageView) convertView.findViewById(R.id.image);  
  98.             oneView.remove = (Button) convertView.findViewById(R.id.remove);  
  99.             convertView.setTag(oneView);//把View和某个对象关联起来  
  100.         } else {  
  101.             oneView = (OneView) convertView.getTag();  
  102.         }  
  103.         JSONObject jObject = null;  
  104.         try {  
  105.             jObject = list.getJSONObject(position);//根据position获取集合类中某行数据  
  106.             oneView.promotion_price.setText("现价¥"+jObject.get("promotion_price").toString());//给该控件设置数据(数据从集合类中来)  
  107.             oneView.price.setText("原价¥"+jObject.get("price").toString());  
  108.             oneView.price.getPaint().setFlags(Paint. STRIKE_THRU_TEXT_FLAG);  
  109.             Float float1 = Float.valueOf(jObject.get("price").toString())- Float.valueOf(jObject.get("promotion_price").toString());  
  110.             if (float1 == 0) {  
  111.                 oneView.sub_price.setVisibility(View.INVISIBLE);  
  112.             }  
  113.             oneView.sub_price.setText(float1.toString()+" ");  
  114.             String strUrl = jObject.get("pic_url").toString() + "_310x310.jpg";  
  115.             oneView.image.setTag(strUrl);  
  116.             Bitmap bm = asyncImageLoader.asyncLoadImage(strUrl, 0, callback);  
  117.             oneView.image.setImageBitmap(null);  
  118.             if(bm==null) {  
  119.                 oneView.image.setBackgroundResource(R.drawable.slt);  
  120.             } else {  
  121.                 oneView.image.setImageBitmap(bm);  
  122.             }  
  123.             bm = null;  
  124.             final String itemID = jObject.get("itemID").toString();  
  125.             oneView.remove.setOnClickListener(new View.OnClickListener() {  
  126.                 @Override  
  127.                 public void onClick(View v) {  
  128.                     // TODO Auto-generated method stub  
  129.                     new MyThread("favor.php?frm=3g&action=favorOrCancel&nickname=" + nickname  
  130.                             +"&id="+itemID+"&type=sp&favor=0"0, handler).start();  
  131.                     Toast.makeText(context, "取消成功"+nickname, 1000).show();  
  132.                       
  133.                 }  
  134.             });  
  135.         } catch (Exception e) {  
  136.             // TODO: handle exception  
  137.         }  
  138.         return convertView;  
  139.     }  
  140.     /** 把每行布局文件的各个控件包装成一个对象  */  
  141.     private class OneView{  
  142.         TextView promotion_price;  
  143.         TextView price;  
  144.         TextView sub_price;  
  145.         ImageView image;  
  146.         Button remove;  
  147.     }  
  148.     //图片下载成功后执行的回调接口  
  149.     LoadFinishCallBack callback = new LoadFinishCallBack() {  
  150.         @Override  
  151.         public void loadFinish(String strUrl, int i, Bitmap bitmap) {  
  152.             if (bitmap != null) {  
  153.                 ImageView imageView = (ImageView) gridView.findViewWithTag(strUrl);  
  154.                 if(imageView != null) {  
  155.                     imageView.setImageBitmap(bitmap);  
  156.                 }  
  157.             }  
  158.         };  
  159.     };  
  160.     private Handler handler = new Handler() {  
  161.         public void handleMessage(android.os.Message msg) {  
  162.             if (msg.what == 0){  
  163.                 String string = (String) msg.obj;  
  164.                 if("1".equals(string)){  
  165.                     Toast.makeText(context, "取消成功"1000).show();  
  166.                 }  
  167.             }  
  168.         };  
  169.     };  
  170. }  

你可能感兴趣的:(Android开发)