android 网络加载图片,对图片资源进行优化,并且实现内存双缓存 + 磁盘缓存_移动开发_编程开发_程序员俱乐部

中国优秀的程序员网站程序员频道CXYCLUB技术地图
热搜:
更多>>
 
您所在的位置: 程序员俱乐部 > 编程开发 > 移动开发 > android 网络加载图片,对图片资源进行优化,并且实现内存双缓存 + 磁盘缓存

android 网络加载图片,对图片资源进行优化,并且实现内存双缓存 + 磁盘缓存

 2016/5/12 5:30:59  xiaoxiaojia  程序员俱乐部  我要评论(0)
  • 摘要:经常会用到网络文件比如查看大图片数据资源优化的问题,当然用开源的项目Android-Universal-Image-Loader或者ignition都是个很好的选择。在这里把原来写过的优化的代码直接拿出来,经过测试千张图片效果还是不错的。免费培训课:http://www.jinhusns.com/Products/Curriculum/?type=xcj工程目录至于Activity就是加载了1个网格布局01./**02.*实现异步加载和2级缓存03.*/04
  • 标签:android 实现 图片 资源 网络 优化 内存 缓存

经常会用到 网络文件 比如查看大图片数据 资源优化的问题,当然用开源的项目  Android-Universal-Image-Loader  或者 ignition 都是个很好的选择。

在这里把原来 写过的优化的代码直接拿出来,经过测试千张图片效果还是不错的。

免费培训课:http://www.jinhusns.com/Products/Curriculum/?type=xcj

 

工程目录

 

至于 Activity 就是加载了 1个网格布局

class="number">01./** 02.*   实现 异步加载 和   2级缓存 03.*/ 04.public class ImagedownActivity extends Activity { 05.  06.public static String filepath; 07.@Override 08.public void onCreate(Bundle savedInstanceState) { 09.super.onCreate(savedInstanceState); 10.setContentView(R.layout.main); 11.filepath =   this.getCacheDir().getAbsolutePath(); 12.GridView gv=(GridView)findViewById(R.id.gridview01); 13.//设置列数 14.gv.setNumColumns(3); 15.//配置适配器 16.gv.setAdapter(new Myadapter(this)); 17.} 18.  19.@Override 20.protected void onDestroy() { 21.// TODO Auto-generated method stub 22.//activity 销毁时,清除缓存 23.MyImageLoader.removeCache(filepath); 24.super.onDestroy(); 25.} 26.  27.}

 接下来 Myadapter.java(给网格每个item塞入图片 )在生成每个 item 异步请求网络获取image

01.public class Myadapter extends BaseAdapter { 02.private Context context; 03.private String  root ="http://192.168.0.100:8080/Android_list/"; 04.private String[] URLS; 05.private final MyImageLoader  myImageLoader = new MyImageLoader(context);; 06.  07./** 08.* adapter 初始化的时候早一堆数据 09.* 这里我请求的是自己搭的服务器 10.* @param context 11.*/ 12.public  Myadapter(Context context){ 13.this.context =context; 14.URLS = new String[999]; 15.for (int i = 0; i < 999; i++) { 16.URLS[i] = root + (i+1)+".jpg"; 17.}   18.} 19.  20.  21.@Override 22.public int getCount() { 23.return URLS.length; 24.} 25.  26.@Override 27.public Object getItem(int position) { 28.return URLS[position]; 29.} 30.  31.@Override 32.public long getItemId(int position) { 33.return URLS[position].hashCode(); 34.} 35.  36.  37.  38.@Override 39.public View getView(int position, View view, ViewGroup parent) { 40.ImageView imageView; 41.if(view==null){ 42.imageView=new ImageView(context); 43.imageView.setLayoutParams(new GridView.LayoutParams(200,190)); 44.imageView.setAdjustViewBounds(false); 45.imageView.setScaleType(ImageView.ScaleType.CENTER_CROP); 46.imageView.setPadding(5, 5, 5, 5); 47.}else{ 48.imageView=(ImageView)view; 49.} 50.myImageLoader.downLoad(URLS[position], (ImageView)imageView , context); 51.return imageView; 52.} 53.}

 MyImageLoader.java

001.public class MyImageLoader {  002.  003.//最大内存  004.final static int memClass = (int) Runtime.getRuntime().maxMemory();    005.private Context context;  006.  007.// 是否缓存到硬盘  008.private boolean  diskcache = true 009.  010.// 定义一级 缓存的图片数  011.private static final int catch_num = 10 012.  013.// 定义二级缓存 容器  软引用  014.private static ConcurrentHashMap<String, SoftReference<Bitmap>> current_hashmap = new ConcurrentHashMap<String, SoftReference<Bitmap>>();  015.  016.// 定义一级缓存容器  强引用       (catch_num ,0.75f,true) 默认参 数                                                                                                                        2.加载因子默认        3.排序模式 true  017.private static LinkedHashMap<String, Bitmap> link_hashmap = new LinkedHashMap<String, Bitmap>(catch_num ,0.75f,true) {  018.  019.// 必须实现的方法  020.protected boolean removeEldestEntry(java.util.Map.Entry<String, Bitmap> eldest) {  021./** 当一级缓存中 图片数量大于 定义的数量 放入二级缓存中 022.*/  023.if (this.size() > catch_num) {  024.// 软连接的方法 存进二级缓存中  025.current_hashmap.put(eldest.getKey(), new SoftReference<Bitmap>(  026.eldest.getValue()));  027.//缓存到本地  028.cancheToDisk(eldest.getKey(),eldest.getValue() );  029.  030.return true 031. 032.return false 033.};  034.};  035.  036.public MyImageLoader(Context context) {  037.  038. 039.  040.  041./**    042.*  外部调用此方法   进行下载图片   043.*/  044.public void downLoad(String key , ImageView imageView,Context context){  045.// 先从缓存中找   。    046.context = this.context;  047.  048.Bitmap bitmap = getBitmapFromCache(key);  049.if( null!= bitmap){   050.imageView.setImageBitmap(bitmap);  051.cancleDownload(key, imageView);         //取消下载  052.return 053.}      054.  055.// 缓存中 没有  把当前的 imageView 给他 得到 task   056.if(cancleDownload(key, imageView)){     //没有任务进行。,。。开始下载  057.ImageDownloadTask task = new ImageDownloadTask(imageView);  058.Zhanwei_Image  zhanwei_image = new Zhanwei_Image(task);  059.//先把占位的图片放进去  060.imageView.setImageDrawable(zhanwei_image);  061.// task执行任务  062.task.execute(key);   063. 064. 065.  066.  067./** 此方法 用于优化  : 用户直接 翻到 哪个 就先加载 哪个、 068.* @param key                - URL 069.* @param imageView          - imageView 070.*  core: 给当前的 imageView 得到给他下载的 task 071.*/  072.  073.private boolean cancleDownload(String key,ImageView imageView){  074.// 给当前的 imageView 得到给他下载的 task  075.ImageDownloadTask task = getImageDownloadTask(imageView);  076.if(null != task){  077.String down_key = task.key;  078.if( null == down_key || !down_key.equals(key)){  079.task.cancel(true);        // imageview 和 url 的key不一样       取消下载     080.}else 081.return false;      //正在下载:   082.}    083. 084.return true;            //没有正在下载  085. 086.  087.  088.  089.//  public void getThisProcessMemeryInfo() {  090.//        int pid = android.os.Process.myPid();  091.//        android.os.Debug.MemoryInfo[] memoryInfoArray = activityManager.getProcessMemoryInfo(new int[] {pid});  092.//        System.out.println("本应用当前使用了" + (float)memoryInfoArray[0].getTotalPrivateDirty() / 1024 + "mb的内存");  093.//    }  094.  095.  096.  097./** 098.* 从缓存中得到 图片的方法 1.先从一级 缓存找 linkhashmap 不是线程安全的 必须要加同步 099.*/  100.public Bitmap getBitmapFromCache(String key) {  101.//1.先在一级缓存中找  102.synchronized (link_hashmap) {  103.Bitmap bitmap = link_hashmap.get(key);  104.if (null != bitmap) {  105.link_hashmap.remove(key);  106.// 按照 LRU是Least Recently Used 近期最少使用算法 内存算法 就近 就 原则 放到首位  107.link_hashmap.put(key, bitmap);  108.System.out.println(" 在缓存1中找图片了 =" +key);  109.return bitmap;  110. 111. 112.  113.// 2. 到二级 缓存找  114.SoftReference<Bitmap> soft = current_hashmap.get(key);  115.if (soft != null) {  116.//得到 软连接 中的图片  117.Bitmap soft_bitmap = soft.get();        118.if (null != soft_bitmap) {  119.System.out.println(" 在缓存2中找图片了 =" +key);  120.return soft_bitmap;  121. 122.} else 123.// 没有图片的话 把这个key删除  124.current_hashmap.remove(key);        125. 126.  127.  128.//3.都没有的话去从外部缓存文件读取  129.if(diskcache){  130.Bitmap bitmap = getBitmapFromFile(key);  131.if(bitmap!= null){  132.link_hashmap.put(key, bitmap);   //将图片放到一级缓存首位  133.return bitmap;  134. 135. 136.  137.return null 138. 139.  140.  141./** 142.* 缓存到本地文件 143.* @param key 144.* @param bitmap 145.*/  146.public static void cancheToDisk(String key ,Bitmap bitmap ){  147.//2.缓存bitmap至/data/data/packageName/cache/文件夹中  148.try 149.String fileName = getMD5Str(key);  150.String filePath = ImagedownActivity.filepath + "/" + fileName;  151.System.out.println("缓存到本地===" + filePath);  152.FileOutputStream fos = new FileOutputStream(filePath);  153.bitmap.compress(Bitmap.CompressFormat.JPEG, 100, fos);  154.  155.} catch (Exception e) {  156.  157. 158. 159.  160.  161./** 162.* 从外部文件缓存中获取bitmap 163.* @param url 164.* @return 165.*/  166.private Bitmap getBitmapFromFile(String url){  167.Bitmap bitmap = null 168.String fileName = getMD5Str(url);  169.if(fileName == null){  170.return null 171.}     172.String filePath = ImagedownActivity.filepath + "/" + fileName;        173.try 174.FileInputStream fis = new FileInputStream(filePath);  175.bitmap = BitmapFactory.decodeStream(fis);  176.System.out.println("在本地缓存中找到图片==="+ filePath);  177.} catch (FileNotFoundException e) {  178.System.out.println("getBitmapFromFile==="+ e.toString());  179.e.printStackTrace();  180.bitmap = null 181. 182.return bitmap;  183. 184.  185.  186.  187./** 188.* 清理文件缓存 189.* @param dirPath 190.* @return 191.*/  192.public static boolean removeCache(String dirPath) {  193.File dir = new File(dirPath);  194.File[] files = dir.listFiles();  195.if(files == null || files.length == 0) {  196.return true 197. 198.int dirSize = 0 199.//这里删除所有的缓存  200.int all_ = (int) ( 1 * files.length + 1);  201.//对files 进行排序  202.Arrays.sort(files, new FileLastModifiedSort());  203.for (int i = 0; i < all_ ; i++) {  204.files[i].delete();  205. 206.return true 207. 208.  209.  210./** 211.* 根据文件最后修改时间进行排序 212.*/  213.private static class FileLastModifiedSort implements Comparator<File> {  214.@Override  215.public int compare(File lhs, File rhs) {  216.if(lhs.lastModified() > rhs.lastModified()) {  217.return 1 218.} else if(lhs.lastModified() == rhs.lastModified()) {  219.return 0 220.} else 221.return -1 222. 223. 224. 225.  226.  227./**   228.* MD5 加密   229.*/     230.private static String getMD5Str(String str) {     231.MessageDigest messageDigest = null;     232.try {     233.messageDigest = MessageDigest.getInstance("MD5");     234.messageDigest.reset();     235.messageDigest.update(str.getBytes("UTF-8"));     236.} catch (NoSuchAlgorithmException e) {     237.System.out.println("NoSuchAlgorithmException caught!");     238.return null 239.} catch (UnsupportedEncodingException e) {     240.e.printStackTrace();  241.return null 242.}     243.  244.byte[] byteArray = messageDigest.digest();     245.StringBuffer md5StrBuff = new StringBuffer();     246.for (int i = 0; i < byteArray.length; i++) {                 247.if (Integer.toHexString(0xFF & byteArray[i]).length() == 1)     248.md5StrBuff.append("0").append(Integer.toHexString(0xFF & byteArray[i]));     249.else     250.md5StrBuff.append(Integer.toHexString(0xFF & byteArray[i]));     251.}     252.return md5StrBuff.toString();     253.}    254.  255.  256.// ------------------------ 异步加载----------------------------  257./** 258.*  占位的 图片 或者 颜色      用来绑定 相应的图片 259.*/    260.class Zhanwei_Image extends ColorDrawable{  261.//里面存放 相应 的异步 处理时加载好的图片 ----- 相应的 task  262.private final WeakReference<ImageDownloadTask>  taskReference;  263.public Zhanwei_Image(ImageDownloadTask task){     264.super(Color.BLUE);  265.taskReference = new WeakReference<MyImageLoader.ImageDownloadTask>(task);   266.}    267.// 返回去这个 task 用于比较  268.public ImageDownloadTask getImageDownloadTask(){  269.return taskReference.get();  270. 271. 272.  273.  274.// 根据 给 的 iamgeView、 得到里面的 task  用于和当前的 task比较是不是同1个  275.private ImageDownloadTask getImageDownloadTask(ImageView imageView){  276.if( null != imageView){  277.Drawable drawable = imageView.getDrawable();      278.if( drawable instanceof Zhanwei_Image)  279.return ((Zhanwei_Image)drawable).getImageDownloadTask();  280.  281. 282.return null 283. 284.  285.  286.  287./** 288.* 把图片 添加到缓存中 289.*/  290.public void addBitmap(String key, Bitmap bitmap) {  291.if (null != bitmap) {  292.synchronized (link_hashmap) {         // 添加到一级 缓存中  293.link_hashmap.put(key, bitmap);  294. 295. 296. 297.  298.  299./** 在后台 加载每个图片 300.*  第一个参数 第2个要进度条不 第三个返回结果 bitmap 301.*/  302.class ImageDownloadTask extends AsyncTask<String, Void, Bitmap> {  303.  304.private String key;  305.private WeakReference<ImageView> imgViReference;  306.  307.public ImageDownloadTask(ImageView imageView) {  308.//imageView 传进来 。。要给哪个iamgeView加载图片  309.imgViReference = new WeakReference<ImageView>(  310.imageView);  311. 312.  313.@Override  314.protected Bitmap doInBackground(String... params){  315.key = params[0];  316.//调用下载函数 根据 url 下载        317.return downloadBitmap(key);  318. 319.  320.@Override  321.protected void onPostExecute(Bitmap result) {  322.if(isCancelled()){  323.result = null 324. 325.  326.System.out.println("result=="+ result.getByteCount()+"---memClassmemery="+memClass);  327.  328.if(null!= result){  329.//保存到缓存中  330.addBitmap(key, result);  331.ImageView  imageView = imgViReference.get();  332.if( null != imageView){    333.//向 imageView 里面放入 bitmap           334.ImageDownloadTask task = getImageDownloadTask(imageView);  335.  336./** 337.*  判断 是不是 同一个 task( ) 338.*  如果当前这个 task  ==  imageView 里面的那个 task 就是同1个 339.*/  340.if( this == task ){  341.imageView.setImageBitmap(result);  342.  343. 344. 345. 346. 347. 348.  349.  350./** 351.* 连接网络 客户端 下载图片 352.*/  353.private Bitmap downloadBitmap(String url) {  354.  355.final HttpClient client = AndroidHttpClient.newInstance("Android");  356.final HttpGet getRequest = new HttpGet(url);   357.try 358.HttpResponse response = client.execute(getRequest);  359.final int statusCode = response.getStatusLine().getStatusCode();  360.  361.if (statusCode != HttpStatus.SC_OK) {  362.  363.Log.w("ImageDownloader", "Error " + statusCode + " while retrieving bitmap from " + url);  364.return null 365. 366.  367.final HttpEntity entity = response.getEntity();  368.if (entity != null) {  369.InputStream inputStream = null 370.try 371.  372.inputStream = entity.getContent();                   373./** 374.*  1.没有压缩直接将生成的bitmap返回去 375.*/  376.//                  return BitmapFactory.decodeStream(inputStream);  377.  378./** 379.*  2.得到data后在这里把图片进行压缩 380.*/  381.byte[] data = StreamTool.read(inputStream);   382.return  BitmapManager.scaleBitmap(context, data, 0.3f);  383.//                   return BitmapFactory.decodeStream(new FlushedInputStream(inputStream));  384.} finally 385.if (inputStream != null) {  386.inputStream.close();  387. 388.entity.consumeContent();  389. 390. 391.} catch (IOException e) {  392.getRequest.abort();  393.} catch (IllegalStateException e) {  394.getRequest.abort();  395.} catch (Exception e) {  396.getRequest.abort();  397.} finally 398.if ((client instanceof AndroidHttpClient)) {  399.((AndroidHttpClient) client).close();  400. 401. 402.return null 403. 404.  405.}

 StreamTool.java

01.public class StreamTool {  02.  03.public static  byte[] read(InputStream in) throws Exception{  04.ByteArrayOutputStream  out_byte = new ByteArrayOutputStream();  05.byte[] buff = new byte[1024];  06.int len=0 07.while((len = in.read(buff))!= -1){  08.//写到内存中  字节流  09.out_byte.write( buff, 0 , len);  10.}     11.out_byte.close();     12.// 把内存数据返回  13.return  out_byte.toByteArray();   14. 15.}

 BitmapManager.java ( 这个类里面对 网络资源的图片 进行了优化)

001.public class BitmapManager { 002.  003./** 004.* 按屏幕适配Bitmap 005.*/ 006.public static Bitmap scaleBitmap(Context context, byte[] data , float percent) { 007.  008.//这里我不获取了,假设是下面这个分辨率 009.int screenWidth =   540; 010.int screenrHeight = 950; 011.//设置 options 012.BitmapFactory.Options options = new BitmapFactory.Options(); 013./** 014.*  BitmapFactory.Options这个类,有一个字段叫做 inJustDecodeBounds.SDK中对这个成员的说明是这样的: 015.*  If set to true, the decoder will return null (no bitmap), but the out… 016.*  也就是说,如果我们把它设为true,那么BitmapFactory.decodeFile(String path, Options opt)并不会真的返回一个Bitmap给你, 017.*  它仅仅会把它的宽,高取回来给你,这样就不会占用太多的内存,也就不会那么频繁的发生OOM了。 018.*/ 019.options.inJustDecodeBounds = true; 020.  021.//读取 022.Bitmap bitmap = BitmapFactory.decodeByteArray(data, 0, data.length, options); 023.  024.int imgWidth = options.outWidth; 025.int imgHeight = options.outHeight; 026.  027.//如果比你设置的宽高大  就进行缩放, 028.if(imgWidth > screenWidth * percent || imgHeight > screenrHeight * percent) { 029.options.inSampleSize = calculateInSampleSize(options, screenWidth, screenrHeight, percent); 030.} 031.  032.  033./** 034.* If set to true, the decoder will return null (no bitmap), but the out... fields will still be set, allowing the caller 035.* to query the bitmap without having to allocate the memory for its pixels. 036.* 037.* 如果设置成 true,这个编码将会返回1个null , 但是那个区域仍将被设置(也就是存在),允许(调用者)去查询那个没有分配 内存的像素  bitmap 038.*/ 039.options.inJustDecodeBounds = false; 040.  041./** 042.*  Android的Bitmap.Config给出了bitmap的一个像素所对应的存储方式, 043.*  有RGB_565,ARGB_8888,ARGB_4444,ALPHA_8四种。RGB_565表示的是红绿蓝三色分别用5,6,5个比特来存储, 044.*  一个像素占用了5+6+5=16个比特。ARGB_8888表示红绿蓝和半透明分别用8,8,8,8个比特来存储, 045.*  一个像素占用了8+8+8+8=32个比特。这样的话如果图片是以RGB_8888读入的,那么占用内存的大小将是RGB_565读入方式的2倍。 046.*  通常我们给Imagview加载图片是通过setDrawable或者在xml文件中用android:src来设置 047.*  默认的加载图片大小的方式是以RGB_8888读入的。 048.* 049.*/ 050.options.inPreferredConfig = Bitmap.Config.RGB_565; 051.  052./** 053.* If this is set to true, then the resulting bitmap will allocate its pixels such that they can be purged 054.* if the system needs to reclaim memory. 055.* 056.* 如果设置成 true, 这个结果bitmap 将会被分配像素,这样他们就能被 系统回收了,当系统需要回收内存的时候 057.*/ 058.options.inPurgeable = true; 059.  060./** 061.* This field works in conjuction with inPurgeable. 062.* 这个方法是在   inPurgeable 的基础上工作的 063.*/ 064.options.inInputShareable = true; 065.  066.  067.bitmap = BitmapFactory.decodeByteArray(data, 0, data.length, options); 068.  069.System.out.println("data==="+  data.length +"  change == bitmap byte "+ bitmap.getByteCount()); 070.return bitmap; 071.} 072.  073.  074.  075.//                                                    options       reqWidth 屏幕宽      reqHeight屏幕高      你的view是屏幕的多大 076.public static int calculateInSampleSize(BitmapFactory.Options options, int screenWidth, int screenHeight ,float percent) { 077.  078.// 原始图片宽高 079.final int height = options.outHeight; 080.final int width = options.outWidth; 081.// 倍数 082.int inSampleSize = 1; 083.  084.if (height > screenHeight * percent || width > screenWidth * percent) { 085.  086.// 计算目标宽高与原始宽高的比值 087.final int inSampleSize_h = Math.round((float) height / (float)( screenHeight * percent)); 088.  089.final int inSampleSize_w = Math.round((float) width / (float)( screenWidth * percent)); 090.  091.// 选择两个比值中较小的作为inSampleSize的 092.inSampleSize = inSampleSize_h < inSampleSize_w ? inSampleSize_h : inSampleSize_w; 093.  094.System.out.println("inSampleSize===="+ inSampleSize); 095.// 096.if(inSampleSize < 1) { 097.inSampleSize = 1; 098.} 099.} 100.//简单说这个数字就是 缩小为原来的几倍,根据你的image需要占屏幕多大动态算的(比如你用的权重设置layout) 101.return inSampleSize; 102.} 103.}

 这个是代码输出的最多给这个进程分配的内存 128M

可以看到我上面的bitmapManager 里面有个   options.inPreferredConfig   注释写的很清楚,可以上去看一下,接下来贴几种格式的效果图

rgb565  和  argb_444  所占的内存              (54000)

 

看一下 argb_8888                    (  108000)

 

当然可能仔细看的人会看到我一开始截的 鸣人的效果图 上半部分 和 下半部分的颜色会有点问题。上面的rgb_565 生成的,和原图色彩可能会有点出入。

但是内存真心少了一半,所以各种取舍就看个人了,代码注释都谢的很清楚了。

 

至于 : MyImageLoaderLru.java  其实就是    MyImageLoader.java

先贴出代码不同地方的代码 : 就是在强引用的地方  把  LinkedHashMap 换成了 LruCache

 

  01.// 获取单个进程可用内存的最大值  02.// 方式一:使用ActivityManager服务(计量单位为M)  03./*int memClass = ((ActivityManager) context.getSystemService(Context.ACTIVITY_SERVICE)).getMemoryClass();*/  04.// 方式二:使用Runtime类(计量单位为Byte)  05.final static int memClass = (int) Runtime.getRuntime().maxMemory();  06.// 3. 定义一级缓存容器  强引用       (catch_num /2,0.75f,true) 默认参 数                                                                                                                        2.加载因子默认        3.排序模式 true 07.final static int  max = memClass/5; 08.  09.// LruCache 用强引用将  图片放入     LinkedHashMap 10.private static LruCache<String, Bitmap> lrucache = new LruCache<String, Bitmap>(max) { 11.protected int sizeOf(String key, Bitmap value) {  12.if(value != null) {  13.// 计算存储bitmap所占用的字节数  14.return value.getRowBytes() * value.getHeight();  15.} else 16.return 0 17. 18. 19.  20.@Override  21.protected void entryRemoved(boolean evicted, String key, Bitmap oldValue, Bitmap newValue) {  22.if(oldValue != null) {  23.// 当硬引用缓存容量已满时,会使用LRU算法将最近没有被使用的图片转入软引用缓存  24.current_hashmap.put(key, new SoftReference<Bitmap>(oldValue));  25. 26. 27.};

1. 强引用:LruCache 后面再说,其实他内的内部封装的就是1个 LinkedHashMap 。LinkedHashMap 是线程不安全的,所以上面都会用到同步。

2. 软引用:ConcurrentHashMap 是线程安全的,并且支持高并发很有效率,这个后面也会说到,为什么要用 软引用 SoftReference,这个是在系统将要oom时,就会回收

                    软引用的对象资源,所以才会用到他,防止程序出异常

3. 磁盘缓存: 这个经常会看到网易新闻等,应用有些界面你看了很多图片,往上翻很多, 其实没有再次访问网络,会将部分image缓存在sdcard里。

4. 其中1个优化: 当比如用户快速滑动到 最底部,其实是最先加载显示给用户的部分的内容的,这样就是用户看到哪加载哪,1个是快,1个是避免资源浪费。

 

原理: 当用户进入界面加载图片 ,首先会从1级缓存强引用中找,找不到回去2级缓存软引用中找,找不到再去sdcard中找,再找不到才会去请求网络加载资源。

            当然sdcard的缓存 看个人需求是否需要。

 

注: android 4.0 后 对 SoftReference 的回收机制进行了改变,所以你是可以不用 2级缓存的,直接去掉就好了。

          只要控制好你的 lrucache 或者 linkedhashmap就好了。

免费培训课:http://www.jinhusns.com/Products/Curriculum/?type=xcj

 

发表评论
用户名: 匿名