异步下载图片和图片缓存

功能如下:

流程如下:

   RemoteImageViewActivity:

[java]  view plain copy print ?
  1. public class RemoteImageViewActivity extends Activity {    
  2.     /** Called when the activity is first created. */    
  3.     @Override    
  4.     public void onCreate(Bundle savedInstanceState) {    
  5.         super.onCreate(savedInstanceState);    
  6.         setContentView(R.layout.main);    
  7.     
  8.         RemoteImageView img = (RemoteImageView) findViewById(R.id.remote_img);    
  9.         img.setDefaultImage(R.drawable.ic_launcher);    
  10.         img.setImageUrl("http://img2.kwcdn.kuwo.cn:81/star/albumcover/120/7/8/83787_1323997225.jpg");    
  11.     }    
  12.     
  13.     @Override    
  14.     protected void onPause() {    
  15.         // TODO Auto-generated method stub    
  16.         super.onPause();    
  17.     }    
  18. }    

   ImageCache:

[java]  view plain copy print ?
  1. public class ImageCache extends WeakHashMap<String, Bitmap>{    
  2.     
  3.     /**  
  4.      * 判断该url是否存在  
  5.      * @param url  
  6.      * @return  
  7.      */    
  8.     public boolean isCached(String url){    
  9.         return containsKey(url) && get(url) != null;    
  10.     }    
  11. }    

   RemoteImageApplication:

[java]  view plain copy print ?
  1. public class RemoteImageApplication extends Application {    
  2.     
  3.     public static final String TAG = "RemoteImageApplication";    
  4.     
  5.     private static RemoteImageApplication application;    
  6.     
  7.     private ImageCache mImageCache;    
  8.     
  9.     public SharedPreferences prefs = null;    
  10.     
  11.         
  12.     public static RemoteImageApplication getInstance() {    
  13.         return application;    
  14.     }    
  15.     
  16.     @Override    
  17.     public void onCreate() {    
  18.         // TODO Auto-generated method stub    
  19.         super.onCreate();    
  20.     
  21.         application = this;    
  22.     
  23.         mImageCache = new ImageCache();    
  24.     
  25.         prefs = PreferenceManager.getDefaultSharedPreferences(this);    
  26.     }    
  27.     
  28.     public ImageCache getImageCache() {    
  29.         return mImageCache;    
  30.     }    
  31. }    

RemoteSettings:

[java]  view plain copy print ?
  1. public class RemoteSettings {    
  2.     
  3.     public static final String CACHE_SIZE = "cache_size";  //图片缓存保留大小,如果超过该大小,即进行自动清除缓存.    
  4.     
  5. }    

RemoteImageView:

[java]  view plain copy print ?
  1. public class RemoteImageView extends ImageView {    
  2.     
  3.     private Context mContext;    
  4.     
  5.     private static int mCacheSize = 150// 设置的缓存大小。    
  6.     
  7.     private static final int MAX_FAILURES = 3// 下载的尝试请求次数    
  8.     
  9.     private int mFailure; // 下载失败次数    
  10.     
  11.     private String mUrl; // 当前下载的url    
  12.     
  13.     private String mCurrentlyGrabbedUrl; // 当前下载成功的url    
  14.     
  15.     private final static String JAMENDO_DIR = "Android/data/com.teleca.jamendo"// 文件缓存存放的路径.    
  16.     
  17.     private final static long MB = 1073741824;    
  18.     
  19.     public RemoteImageView(Context context, AttributeSet attrs, int defStyle) {    
  20.         super(context, attrs, defStyle);    
  21.         mContext = context;    
  22.     }    
  23.     
  24.     public RemoteImageView(Context context, AttributeSet attrs) {    
  25.         super(context, attrs);    
  26.         mContext = context;    
  27.     }    
  28.     
  29.     public RemoteImageView(Context context) {    
  30.         super(context);    
  31.         mContext = context;    
  32.     }    
  33.     
  34.     /**  
  35.      * 设置默认图片  
  36.      */    
  37.     public void setDefaultImage(Integer resid) {    
  38.         setImageResource(resid);    
  39.     }    
  40.     
  41.     /**  
  42.      * 设置需要异步加载的图片  
  43.      */    
  44.     public void setImageUrl(String url) {    
  45.     
  46.         // 下载失败进行重试,如果重试次数超过规定的限制,则直接返回.    
  47.         if (mUrl != null    
  48.                 && mUrl.equals(url)    
  49.                 && (mCurrentlyGrabbedUrl == null || (mCurrentlyGrabbedUrl != null && !mCurrentlyGrabbedUrl    
  50.                         .equals(url)))) {    
  51.             mFailure++;    
  52.             if (mFailure > MAX_FAILURES) {    
  53.                 Log.e(RemoteImageApplication.TAG, "下载该图片地址失败:" + url);    
  54.                 return;    
  55.             }    
  56.         } else {    
  57.     
  58.             mUrl = url;    
  59.             mFailure = 0;    
  60.         }    
  61.     
  62.         ImageCache imageCache = RemoteImageApplication.getInstance()    
  63.                 .getImageCache();    
  64.     
  65.         if (imageCache.isCached(url)) {    
  66.             setImageBitmap(imageCache.get(url));    
  67.         } else {    
  68.             // 如果内存中没有该缓存,则从文件中进行查找.    
  69.             String fileName = convertUrlToFileName(url); // 进行文件名处理    
  70.     
  71.             String filepath = getDirectory(fileName); // 取得缓存文件夹目录    
  72.     
  73.             String pathFileName = filepath + "/" + fileName; // 组拼文件    
  74.     
  75.             File pathFile = new File(pathFileName);    
  76.             if (!pathFile.exists()) {    
  77.                 try {    
  78.                     pathFile.createNewFile();    
  79.                 } catch (IOException e) {    
  80.                     Log.d(RemoteImageApplication.TAG, "创建图片文件失败:"    
  81.                             + pathFileName);    
  82.                 }    
  83.             }    
  84.     
  85.             Bitmap tbmp = BitmapFactory.decodeFile(pathFileName);    
  86.     
  87.             if (tbmp == null) {    
  88.                 Log.d(RemoteImageApplication.TAG, "图片文件不存在,开始进行下载");    
  89.                 try {    
  90.                     new DownloadTask().execute(url);    
  91.                 } catch (RejectedExecutionException e) {    
  92.                     Log.d(RemoteImageApplication.TAG, "下载失败");    
  93.                 }    
  94.             } else {    
  95.                 Log.i(RemoteImageApplication.TAG, "从文件中加载图片");    
  96.                 RemoteImageApplication.getInstance().getImageCache()    
  97.                         .put(url, tbmp);    
  98.                 this.setImageBitmap(tbmp);    
  99.             }    
  100.     
  101.             updateCacheSize(pathFileName); // 进行检测文件大小,以便于清除缓存.    
  102.     
  103.         }    
  104.     
  105.     }    
  106.     
  107.     private void updateCacheSize(String pathFileName) {    
  108.         // TODO Auto-generated method stub    
  109.         updateSizeCache(pathFileName);    
  110.     
  111.     }    
  112.     
  113.     /**  
  114.      * 检查文件目录是否超过规定的缓存大小  
  115.      *   
  116.      * @param fileName  
  117.      */    
  118.     private void updateSizeCache(String pathFileName) {    
  119.         // TODO Auto-generated method stub    
  120.         mCacheSize = PreferenceManager.getDefaultSharedPreferences(mContext)    
  121.                 .getInt(RemoteSettings.CACHE_SIZE, 100); // 读取设置的缓存大小,前台可以动态设置此值    
  122.     
  123.         if (isSDCardEnable()) {    
  124.             String extStorageDirectory = Environment    
  125.                     .getExternalStorageDirectory().toString(); // 取得SD根路径    
  126.     
  127.             String dirPath = extStorageDirectory + "/" + JAMENDO_DIR    
  128.                     + "/imagecache";    
  129.     
  130.             File dirFile = new File(dirPath);    
  131.     
  132.             File[] files = dirFile.listFiles();    
  133.     
  134.             long dirSize = 0;    
  135.     
  136.             for (File file : files) {    
  137.     
  138.                 dirSize += file.length();    
  139.             }    
  140.     
  141.             if (dirSize > mCacheSize * MB) {    
  142.                 clearCache();    
  143.             }    
  144.         }    
  145.     
  146.     }    
  147.     
  148.     /**  
  149.      * 异步下载图片  
  150.      *   
  151.      * @ClassName: DownloadTask  
  152.      * @author 姜涛  
  153.      * @version 1.0 2012-1-15 下午5:06:21  
  154.      */    
  155.     class DownloadTask extends AsyncTask<String, Void, String> {    
  156.     
  157.         private String mTaskUrl;    
  158.         private Bitmap mBmp = null;    
  159.     
  160.         @Override    
  161.         public void onPreExecute() {    
  162.             // loadDefaultImage();    
  163.             super.onPreExecute();    
  164.         }    
  165.     
  166.         @Override    
  167.         public String doInBackground(String... params) {    
  168.     
  169.             mTaskUrl = params[0];    
  170.             InputStream stream = null;    
  171.             URL imageUrl;    
  172.             Bitmap bmp = null;    
  173.     
  174.             try {    
  175.                 imageUrl = new URL(mTaskUrl);    
  176.                 try {    
  177.                     stream = imageUrl.openStream();    
  178.                     bmp = BitmapFactory.decodeStream(stream);    
  179.                     try {    
  180.                         if (bmp != null) {    
  181.                             mBmp = bmp;    
  182.                             RemoteImageApplication.getInstance()    
  183.                                     .getImageCache().put(mTaskUrl, bmp);    
  184.                             Log.d(RemoteImageApplication.TAG,    
  185.                                     "图片缓存到application中: " + mTaskUrl);    
  186.     
  187.                         }    
  188.                     } catch (NullPointerException e) {    
  189.                         Log.w(RemoteImageApplication.TAG, "下载失败,图片为空:"    
  190.                                 + mTaskUrl);    
  191.                     }    
  192.                 } catch (IOException e) {    
  193.                     Log.w(RemoteImageApplication.TAG, "无法加载该url:" + mTaskUrl);    
  194.                 } finally {    
  195.                     try {    
  196.                         if (stream != null) {    
  197.                             stream.close();    
  198.                         }    
  199.                     } catch (IOException e) {    
  200.                     }    
  201.                 }    
  202.     
  203.             } catch (MalformedURLException e) {    
  204.                 e.printStackTrace();    
  205.             }    
  206.             return mTaskUrl;    
  207.         }    
  208.     
  209.         @Override    
  210.         public void onPostExecute(String url) {    
  211.             super.onPostExecute(url);    
  212.     
  213.             Bitmap bmp = RemoteImageApplication.getInstance().getImageCache()    
  214.                     .get(url);    
  215.             if (bmp == null) {    
  216.                 Log.w(RemoteImageApplication.TAG, "尝试重新下载:" + url);    
  217.                 RemoteImageView.this.setImageUrl(url);    
  218.             } else {    
  219.     
  220.                 RemoteImageView.this.setImageBitmap(bmp);    
  221.                 mCurrentlyGrabbedUrl = url;    
  222.                 saveBmpToSd(mBmp, url);    
  223.     
  224.             }    
  225.         }    
  226.     
  227.     };    
  228.     
  229.     /**  
  230.      * 把图片保存到本地  
  231.      *   
  232.      * @param bm  
  233.      * @param url  
  234.      */    
  235.     private void saveBmpToSd(Bitmap bm, String url) {    
  236.     
  237.         if (bm == null) {    
  238.             return;    
  239.         }    
  240.     
  241.         if (mCacheSize == 0) {    
  242.             return;    
  243.         }    
  244.     
  245.         String filename = convertUrlToFileName(url);    
  246.         String dir = getDirectory(filename);    
  247.         File file = new File(dir + "/" + filename);    
  248.     
  249.         try {    
  250.             file.createNewFile();    
  251.             OutputStream outStream = new FileOutputStream(file);    
  252.             bm.compress(Bitmap.CompressFormat.JPEG, 100, outStream);    
  253.             outStream.flush();    
  254.             outStream.close();    
  255.     
  256.             Log.i(RemoteImageApplication.TAG, "图片已保存到sd卡");    
  257.     
  258.         } catch (FileNotFoundException e) {    
  259.             Log.w(RemoteImageApplication.TAG, "无法找到文件目录");    
  260.     
  261.         } catch (IOException e) {    
  262.             Log.w(RemoteImageApplication.TAG, "操作文件出错");    
  263.         }    
  264.     
  265.     }    
  266.     
  267.     /**  
  268.      * 组拼文件名,后缀名用dat代替,避免别人使用图片管理器搜索出这种对于她们无用的图片.  
  269.      *   
  270.      * @param url  
  271.      * @return  
  272.      */    
  273.     private String convertUrlToFileName(String url) {    
  274.         String filename = url;    
  275.         filename = filename.replace("http://""");    
  276.         filename = filename.replace("/"".");    
  277.         filename = filename.replace(":"".");    
  278.         filename = filename.replace("jpg""dat");    
  279.         filename = filename.replace("png""dat");    
  280.         return filename;    
  281.     }    
  282.     
  283.     /**  
  284.      * 返回缓存图片所存放的文件夹  
  285.      *   
  286.      * @param filename  
  287.      * @return  
  288.      */    
  289.     private String getDirectory(String filename) {    
  290.     
  291.         String extStorageDirectory = Environment.getExternalStorageDirectory()    
  292.                 .toString(); // 取得SD根路径    
  293.     
  294.         String dirPath = extStorageDirectory + "/" + JAMENDO_DIR    
  295.                 + "/imagecache";    
  296.     
  297.         File dirFile = new File(dirPath);    
  298.     
  299.         if (!dirFile.exists()) {    
  300.             dirFile.mkdirs();    
  301.         }    
  302.     
  303.         return dirPath;    
  304.     
  305.     }    
  306.     
  307.     /**  
  308.      * 清除缓存  
  309.      */    
  310.     private void clearCache() {    
  311.     
  312.         if (isSDCardEnable()) {    
  313.             String extStorageDirectory = Environment    
  314.                     .getExternalStorageDirectory().toString(); // 取得SD根路径    
  315.     
  316.             String dirPath = extStorageDirectory + "/" + JAMENDO_DIR    
  317.                     + "/imagecache";    
  318.     
  319.             File dir = new File(dirPath);    
  320.     
  321.             File[] files = dir.listFiles(); // 取得该目录下的所有文件    
  322.     
  323.             if (files == null || files.length == 0) {    
  324.                 return;    
  325.             }    
  326.     
  327.             for (File file : files) {    
  328.                 file.delete();    
  329.             }    
  330.     
  331.             Log.d(RemoteImageApplication.TAG, "已清除缓存:" + dirPath);    
  332.         }    
  333.     }    
  334.     
  335.     /**  
  336.      * 判断SD卡是否可用  
  337.      */    
  338.     public static boolean isSDCardEnable() {    
  339.     
  340.         return Environment.getExternalStorageState().equals(    
  341.                 Environment.MEDIA_MOUNTED);    
  342.     }    
  343.     
  344. }    
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值