仿新浪微博2014之登陆界面二(异步加载图片和缓存)

来源:互联网 发布:淘宝如何进行身份认证 编辑:程序博客网 时间:2024/05/17 06:51
: Android开发 343人阅读 评论(0) 收藏 举报
[java] view plaincopy在CODE上查看代码片派生到我的代码片
  1. 对于社交和资讯类应用,从网络获取图片并显示的功能必不可少了,异步加载图片和缓存,可以加快图片的显示和操作的流畅度,提高用户体验。  

我先写了一个图片加载管理器ImageLoaderManager.java

代码如下:

[java] view plaincopy在CODE上查看代码片派生到我的代码片
  1. package com.xhq.common;  
  2.   
  3. import java.io.FileInputStream;  
  4. import java.io.FileNotFoundException;  
  5. import java.io.FileOutputStream;  
  6. import java.io.IOException;  
  7. import java.io.InputStream;  
  8. import java.io.UnsupportedEncodingException;  
  9. import java.lang.ref.SoftReference;  
  10. import java.net.HttpURLConnection;  
  11. import java.net.URL;  
  12. import java.security.MessageDigest;  
  13. import java.security.NoSuchAlgorithmException;  
  14. import java.util.Map;  
  15.   
  16. import android.graphics.Bitmap;  
  17. import android.graphics.BitmapFactory;  
  18. import android.os.Environment;  
  19. import android.support.v4.util.LruCache;  
  20. import android.util.Log;  
  21.   
  22.   
  23. public class ImageLoaderManager  
  24. {  
  25.     private final String TAG = "ImageLoaderManager";  
  26.     private LruCache<String, Bitmap> mCache = null;  
  27.     private String cacheDir = null;  
  28.     public ImageLoaderManager(LruCache<String, Bitmap> cache)  
  29.     {  
  30.         this.mCache = cache;  
  31.     }  
  32.       
  33.     public void setCacheDir(String dir)  
  34.     {  
  35.         Log.d(TAG, "缓存目录:" + dir);  
  36.         this.cacheDir = dir;  
  37.     }  
  38.   
  39.     public Bitmap getBitmapFromUrl(String url)  
  40.     {  
  41.         Log.d(TAG, "getBitmapFromUrl:" + url);  
  42.         Bitmap bitmap = null;  
  43.         try  
  44.         {  
  45.             URL u = new URL(url);  
  46.             HttpURLConnection conn = (HttpURLConnection) u.openConnection();  
  47.             InputStream is = conn.getInputStream();  
  48.             bitmap = BitmapFactory.decodeStream(is);  
  49.             Log.d(TAG, "save to cache:" + url);  
  50.             mCache.put(url, bitmap);  
  51.             String fileName = getMD5Str(url);  
  52.             String filePath = this.cacheDir  + fileName;  
  53.             try  
  54.             {  
  55.                 FileOutputStream fos = new FileOutputStream(filePath);  
  56.                 bitmap.compress(Bitmap.CompressFormat.PNG, 100, fos);  
  57.                 Log.d(TAG, "save to file:" + filePath);  
  58.             }catch(Exception e)  
  59.             {  
  60.                 Log.d(TAG, " fail to save file:" + filePath);  
  61.             }  
  62.             is.close();  
  63.             conn.disconnect();  
  64.             return bitmap;  
  65.         } catch (IOException e)  
  66.         {  
  67.             e.printStackTrace();  
  68.             return null;  
  69.         }  
  70.     }  
  71.   
  72.     public Bitmap getBitmapFromCache(String url)  
  73.     {  
  74.         Bitmap bitmap = null;  
  75.         synchronized (mCache)  
  76.         {  
  77.             if (mCache.get(url) != null)  
  78.             {  
  79.                 bitmap = mCache.get(url);  
  80.                 if (bitmap != null)  
  81.                 {  
  82.                     return bitmap;  
  83.                 }  
  84.             }  
  85.             Log.d(TAG, "get from cache:" + url);  
  86.             bitmap = getBitmapFromFile(url);  
  87.             if (bitmap != null)  
  88.             {  
  89.                 mCache.put(url, bitmap);  
  90.             }  
  91.             return bitmap;  
  92.         }  
  93.     }  
  94.   
  95.     private Bitmap getBitmapFromFile(String url)  
  96.     {  
  97.         Bitmap bitmap = null;  
  98.         String fileName = getMD5Str(url);  
  99.         if (fileName == null)  
  100.             return null;  
  101.         String filePath = cacheDir + "/" + fileName;  
  102.         try  
  103.         {  
  104.             FileInputStream fis = new FileInputStream(filePath);  
  105.             bitmap = BitmapFactory.decodeStream(fis);  
  106.         } catch (FileNotFoundException e)  
  107.         {  
  108.             e.printStackTrace();  
  109.             bitmap = null;  
  110.         }  
  111.         return bitmap;  
  112.     }  
  113.   
  114.     /** 
  115.      * MD5 加密 
  116.      */  
  117.     private static String getMD5Str(String str)  
  118.     {  
  119.         MessageDigest messageDigest = null;  
  120.         try  
  121.         {  
  122.             messageDigest = MessageDigest.getInstance("MD5");  
  123.             messageDigest.reset();  
  124.             messageDigest.update(str.getBytes("UTF-8"));  
  125.         } catch (NoSuchAlgorithmException e)  
  126.         {  
  127.             System.out.println("NoSuchAlgorithmException caught!");  
  128.             return null;  
  129.         } catch (UnsupportedEncodingException e)  
  130.         {  
  131.             e.printStackTrace();  
  132.             return null;  
  133.         }  
  134.   
  135.         byte[] byteArray = messageDigest.digest();  
  136.         StringBuffer md5StrBuff = new StringBuffer();  
  137.         for (int i = 0; i < byteArray.length; i++)  
  138.         {  
  139.             if (Integer.toHexString(0xFF & byteArray[i]).length() == 1)  
  140.                 md5StrBuff.append("0").append(  
  141.                         Integer.toHexString(0xFF & byteArray[i]));  
  142.             else  
  143.                 md5StrBuff.append(Integer.toHexString(0xFF & byteArray[i]));  
  144.         }  
  145.   
  146.         return md5StrBuff.toString();  
  147.     }  
  148. }  

这个图片加载管理器功能主要是通过图片URL加载图片,分为从内存中加载图片和从网络加载图片,内存加载又分为从cache加载和从文件加载,先从cache加载,如果没有该图片就从文件加载。

从网络加载图片后会把图片保存到文件中,下次再加载相同的url图片时就不用从网络加载了。这里主要说一下LruCache  和MD5加密。

LruCache 使用了硬引用和Lru算法,Cache保存一个强引用来限制内容数量,每当Item被访问的时候,此Item就会移动到队列的头部。当cache已满的时候加入新的item时,在队列尾部的item会被回收。

 

这里对图片的URL进行MD5加密主要是为了更方便的在文件中保存和获取图片,因为url的和文件的路径比较相似,系统会识别不了正确的图片路径。

有了图片加载管理器,我们就进行图片的异步加载AsyncImageLoader.java

 

[java] view plaincopy在CODE上查看代码片派生到我的代码片
  1. package com.xhq.common;  
  2.   
  3. import java.util.HashSet;  
  4. import java.util.concurrent.ExecutorService;  
  5. import java.util.concurrent.Executors;  
  6.   
  7. import com.xhq.xweibo.R;  
  8.   
  9. import android.app.Activity;  
  10. import android.content.Context;  
  11. import android.graphics.Bitmap;  
  12. import android.os.Environment;  
  13. import android.os.Handler;  
  14. import android.support.v4.util.LruCache;  
  15. import android.util.Log;  
  16. import android.view.View;  
  17. import android.widget.ImageView;  
  18.   
  19. public class AsyncImageLoader  
  20. {  
  21.     private final String TAG = "AsyncImageLoader";  
  22.     private static HashSet<String> mLoadingUrlSet;  
  23.     private LruCache<String, Bitmap> mMemoryCache;  
  24.     private static ImageLoaderManager mImldmg;  
  25.     private static ExecutorService mExecutorService;  
  26.     private Handler mHandler;  
  27.     private Activity mActitity;  
  28.   
  29.     public interface onLoadCompleteListener  
  30.     {  
  31.         public void onLoadSuccess(View view,Bitmap bmp, String url);  
  32.         public void onLaodFail(View view,String url);  
  33.     }  
  34.   
  35.     public AsyncImageLoader(Context context)  
  36.     {  
  37.         mLoadingUrlSet = new HashSet<String>();  
  38.         mHandler = new Handler();  
  39.           
  40.         int maxMemory = (int) Runtime.getRuntime().maxMemory();  
  41.         int cacheSize = maxMemory / 8;// 给LruCache分配1/8 4M        
  42.         mMemoryCache = new LruCache<String, Bitmap>(cacheSize)  
  43.         {  
  44.             // 必须重写此方法,来测量Bitmap的大小  
  45.             @Override  
  46.             protected int sizeOf(String key, Bitmap value)  
  47.             {  
  48.                 return value.getRowBytes() * value.getHeight();  
  49.             }  
  50.   
  51.         };  
  52.         mImldmg = new ImageLoaderManager(mMemoryCache);  
  53.         Log.d(TAG, "cachesize:" + cacheSize/1024/1024+"MB");  
  54.           
  55.         startThreadPool(2);  
  56.         String appname = context.getResources().getString(R.string.app_name);  
  57.         String sdDir = "/sdcard/"+appname+"/cache/";  
  58.         String dataDir = context.getCacheDir().getAbsolutePath()+"/";  
  59.           
  60.         if(Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED))  
  61.         {  
  62.             if(FileUtil.isDirExist(sdDir, true))  
  63.             {  
  64.                 setCacheDir(sdDir);  
  65.             }  
  66.               
  67.         }else  
  68.         {  
  69.             setCacheDir(dataDir);  
  70.         }     
  71.     }  
  72.   
  73.     public void setCacheDir(String dir)  
  74.     {  
  75.         mImldmg.setCacheDir(dir);  
  76.     }  
  77.   
  78.     /** 开启线程池 */  
  79.     public static void startThreadPool(int poolNum)  
  80.     {  
  81.         if (mExecutorService == null || mExecutorService.isShutdown()  
  82.                 || mExecutorService.isTerminated())  
  83.         {  
  84.             mExecutorService = Executors.newFixedThreadPool((poolNum == 0) ? 1  
  85.                     : poolNum);  
  86.         }  
[java] view plaincopy在CODE上查看代码片派生到我的代码片
  1. }  
[java] view plaincopy在CODE上查看代码片派生到我的代码片
  1. public void loadImage(final ImageView image, final String url,  
  2.         final onLoadCompleteListener onLoadComplete)  
  3. {  
  4.     if (mLoadingUrlSet.contains(url))  
  5.     {  
  6.         Log.d(TAG, url + " is loading");  
  7.         return;  
  8.     }  
  9.     Bitmap bitmap = null;  
  10.     bitmap = mImldmg.getBitmapFromCache(url);  
  11.     if (bitmap != null)  
  12.     {  
  13.         if (onLoadComplete != null)  
  14.         {  
  15.             onLoadComplete.onLoadSuccess(image, bitmap, url);  
  16.         }  
  17.     } else  
  18.     {  
  19.         // 从网络端下载图片  
  20.         mLoadingUrlSet.add(url);  
  21.         mExecutorService.submit(new Runnable()  
  22.         {  
  23.             @Override  
  24.             public void run()  
  25.             {  
  26.                 final Bitmap bitmap = mImldmg.getBitmapFromUrl(url);  
  27.                 mHandler.post(new Runnable()  
  28.                 {  
  29.                     @Override  
  30.                     public void run()  
  31.                     {  
  32.                         if (onLoadComplete != null)  
  33.                         {  
  34.                             if(bitmap != null)  
  35.                             {  
  36.                                 onLoadComplete.onLoadSuccess(image,bitmap, url);  
  37.                             }  
  38.                             else  
  39.                             {  
  40.                                 onLoadComplete.onLaodFail(image,url);  
  41.                             }  
  42.                         }     
  43.                         mLoadingUrlSet.remove(url);                       
  44.                     }  
  45.                 });  
  46.             }  
  47.         });  
  48.     }  
  49. }  
[java] view plaincopy在CODE上查看代码片派生到我的代码片
  1. }  

 

这个图片异步加载类主要使用了线程、线程池和Handler,主要步骤:

1、设置LruCache的大小cachesize,当缓存的图片大于cachesize时,就会把队列未不的图片释放掉

2、设置图片文件的缓存路径,如果有SD卡,我们就设置缓存路径为  sdDir = "/sdcard/"+appname+"/cache/";

     否则就设置缓存路径为    dataDir = context.getCacheDir().getAbsolutePath()+"/";
     我们可以通过  Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED) 来判定是否有SD卡

 

3、开启线程池,由于微博从网络加载图片是比较频繁的,每加载一张图片都和服务器建立一个连接,那么服务器的压力就很大了,所以这里运用线程池来限制连接数

     线程池我们用了ExecutorService 来管理连接线程

4、最后就是在线程中加载图片了,这里运用了Thread 和Handler 来完成异步通知,当加载图片成功或者失败会通过Handler来通知UI线程更新界面

 

 

 

 

 

 

 

 

 

 地址: http://download.csdn.net/category


 

 

版权声明:本文为博主原创文章,未经博主允许不得转载。

0 0
原创粉丝点击