Android开发中图片的三级缓存

1.关于JAVA中的对象引用,分为:强、软、弱、虚。

2.关于JAVA的强引用与软引用:
(1)强引用:JVM不会回收任何具有强引用的对象,内存空间不足时,将抛出OOM异常;
(2)软引用:在内存不足时,JVM将会回收掉具有软引用的对象,从而满足程序运行的需求,以此避免出现OOM导致的程序崩溃。

3.内存缓存部分:
(1)强引用存储区:
LruCache<String,Bitmap> cache = new LruCache<String,Bitmap>();
(2)软引用存储区:
HashMap<String,Bitmap> softBitmapCache = new HashMap<String,SoftReference<Bitmap>>();

5.关于LruCache类的理解:
这个类其实就是一个哈希表,存储键值对。
值得注意的是:LruCache内部存储的图片内存数量超过上限以后,将采用LRU算法删除部分图片。LRU:Least-Recently-Used。
Cache保存一个强引用来限制内容数量,每当Item被访问的时候,此Item就会移动到队列的头部。当cache已满的时候加入新的item时,在队列尾部的item会被回收。

6.从文件缓存中获取图片的流程:
强引用存储区---->软引用存储区---->文件存储----->网络获取---->显示UI

7.问题:在内存缓存中获取图片时,为什么先在强引用存储区查找,再去软引用存储区查找?
答:强引用存储区存储的图片,有上限,超过上限将会采用LRU算法进行删除;软引用存储区的图片,在内存不足时,JVM将会自动删除部分图片。


三级缓存的过程:(以ImageLoader为例)

手机内存和SD卡都可以看成键值对储存,key:图片网址url,value:图片bitmap。

①使用LruCache缓存类,并给它定义空间大小,手机内存的1/8;

        //定义空间
        int max= (int) (Runtime.getRuntime().maxMemory()/8);
        //初始化LruCache对象
        final LruCache<String, Bitmap> lruCache=new LruCache<String, Bitmap>(max){
            @Override
            protected int sizeOf(String key, Bitmap value) {
                return value.getByteCount();
            }
        };

②把图片压缩到SD卡设定的文件夹中(bitmap.compress),压缩大小可以自己修改方法中的第二个参数实现。

 public static void setData(Bitmap bitmap, String fileName){
        String path=Environment.getExternalStorageDirectory().getAbsolutePath()+ File.separator+fileName+".jpg";
        File file=new File(path);
        try {
            FileOutputStream fos=new FileOutputStream(file);
            //bitmap的压缩,实际的图片其实没有被压缩,只是把压缩后的数据保存到fos中了。第二个参数如果是100,表示没有被压缩。
            bitmap.compress(Bitmap.CompressFormat.JPEG,1,fos);
            fos.flush();
            fos.close();
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }


③使用ImageLoader.ImageCache对象的putBitmap()和getBitmap()方法,分别执行存入缓存和从缓存中取出;

     ImageLoader.ImageCache imageCache= new ImageLoader.ImageCache() {
            @Override
            public Bitmap getBitmap(String url) {
                if(External.isUsed()){
                    Bitmap bitmap=External.getData(url);
                    if(bitmap!=null){
                        return bitmap;
                    }else {
                        return lruCache.get(url);
                    }
                }else {
                    return lruCache.get(url);
                }
            }

            @Override
            public void putBitmap(String url, Bitmap bitmap) {
                if(External.isUsed()){
                    External.setData(bitmap, url);
                    lruCache.put(url, bitmap);
                }else {
                    lruCache.put(url, bitmap);
                }
            }
        };

        ImageLoader imageLoader=new ImageLoader(MyApp.getRequestQueue(), imageCache);
        return imageLoader;
    }



<pre style="background-color:#ffffff;color:#000000;font-family:'Consolas';font-size:13.5pt;"><span style="font-family:KaiTi_GB2312;">最后附上完整代码:

文件储存(SD卡)的存取
</span><pre name="code" class="java">package com.example.administrator.cache;

import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.os.Environment;

import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;

/**
 * Created by Administrator on 2016/7/9.
 */
public class External {
    public static boolean isUsed(){
        String state= Environment.getExternalStorageState();
        if(state.equals(Environment.MEDIA_MOUNTED)){
            return true;
        }
        return false;
    }

    public static void setData(Bitmap bitmap, String fileName){
        String path=Environment.getExternalStorageDirectory().getAbsolutePath()+ File.separator+fileName+".jpg";
        File file=new File(path);
        try {
            FileOutputStream fos=new FileOutputStream(file);
            //bitmap的压缩,实际的图片其实没有被压缩,只是把压缩后的数据保存到fos中了。第二个参数如果是100,表示没有被压缩。
            bitmap.compress(Bitmap.CompressFormat.JPEG,1,fos);
            fos.flush();
            fos.close();
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    public static Bitmap getData(String fileName){
        String path=Environment.getExternalStorageDirectory().getAbsolutePath()+File.separator+fileName+".jpg";
        File file=new File(path);
        FileInputStream fis=null;
        ByteArrayOutputStream bos=null;
        try {
            fis=new FileInputStream(file);
            bos=new ByteArrayOutputStream();
            int len=0;
            byte[] b=new byte[1024];
            while ((len=fis.read(b))!=-1){
                bos.write(b,0,len);
                bos.flush();
            }
            byte[] bytes=bos.toByteArray();
            Bitmap bitmap= BitmapFactory.decodeByteArray(bytes, 0, bytes.length);
            return bitmap;
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }

        return null;
    }
}


ImageLoader的二级缓存(三级缓存有空会补上)
package com.example.administrator.cache;

import android.graphics.Bitmap;
import android.util.LruCache;

import com.android.volley.RequestQueue;
import com.android.volley.toolbox.ImageLoader;


/**
 * Created by Administrator on 2016/7/9.
 */
public class FindImage {
    public static ImageLoader getLoader(RequestQueue queue){
        //定义空间
        int max= (int) (Runtime.getRuntime().maxMemory()/8);
        //初始化LruCache对象
        final LruCache<String, Bitmap> lruCache=new LruCache<String, Bitmap>(max){
            @Override
            protected int sizeOf(String key, Bitmap value) {
                return value.getByteCount();
            }
        };

        ImageLoader.ImageCache imageCache= new ImageLoader.ImageCache() {
            @Override
            public Bitmap getBitmap(String url) {
                if(External.isUsed()){
                    Bitmap bitmap=External.getData(url);
                    if(bitmap!=null){
                        return bitmap;
                    }else {
                        return lruCache.get(url);
                    }
                }else {
                    return lruCache.get(url);
                }
            }

            @Override
            public void putBitmap(String url, Bitmap bitmap) {
                if(External.isUsed()){
                    External.setData(bitmap, url);
                    lruCache.put(url, bitmap);
                }else {
                    lruCache.put(url, bitmap);
                }
            }
        };

        ImageLoader imageLoader=new ImageLoader(MyApp.getRequestQueue(), imageCache);
        return imageLoader;
    }
}


 
 





  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值