Android缓存机制

缓存

Android开发中,如果每次访问资源都通过网络访问会导致流量使用和速度慢的情况

对于图片或者另外大的资源的加载(视频,音频),使用缓存就很有必要

两种缓存方法

首先缓存到存储设备上,这样下次加载资源时就不需要使用网络,其次可以缓存到内存中,从内存中加载的速度要高于从存储设备中加载

 

所谓的二级缓存就是指即有内存缓存又有存储设备缓存

 

官方提供了LruCache和DiskLruCache,分别用于内存缓存和存储设备缓存

Lru:Least Recently Used  最近最少使用算法,这种算法的核心思想是缓存快达到预设值时,优先淘汰最少使用的缓存目标

 

LruCache示例代码

        int maxMemory= (int) (Runtime.getRuntime().maxMemory()/1024);
        int cacheSize=maxMemory/8;
        LruCache<String,Bitmap> lruCache=new LruCache<String,Bitmap>(cacheSize){
            @Override
            protected int sizeOf(String key, Bitmap value) {
                return value.getRowBytes()*value.getHeight()/1024;
            }
        };
        Bitmap bitmap=BitmapFactory.decodeResource(getResources(),R.drawable.icon_wallet_x);
        lruCache.put("abc",bitmap);
        lruCache.get("abc");
        lruCache.remove("abc");

这里取进程可用最大内存的1/8来做缓存可用大小,单位设为KB

在sizeOf方法中提供单个缓存目标的大小的计算方法

还可以覆写entryRemoved方法,在LruCache移除旧缓存时调用

put,get,remove对应添加,获取,移除

 

DiskLruCache

DiskLruCache被官方推荐但没有在官方SDK中提供,需要自己去添加依赖

https://github.com/JakeWharton/DiskLruCache

 

open()创建对象

四个参数:第一个参数文件存储路径,第二个版本号(传1就行),第三个单个节点对应数据个数(传1就行),第四个参数缓存的可用大小

edit(key)获取DiskLruCache.Editor对象,editor.newOutputStream获取字节输出流对象

文件写入完成要editor.commit()提交,文件写入异常可以通过editor.abort()回退

get(key)获取DiskLruCache.Snapshot对象,snapshot.getInputStream()获取字节输入流对象

remove(key)移除指定缓存delete()清空缓存并且关闭close()关闭缓存flush()强制缓存操作写入文件系统

size()得到当前缓存大小getMaxSize()获取缓存最大存储大小

注意点:

key的格式要求: [a-z0-9_-]{1,120}

close()之后就不能调用DiskLruCache的任何方法了,一般放在onDestroy()中

remove(key)之后要flush(),否则之后size()获取缓存使用大小会出现问题

示例代码:

public class Main7Activity extends AppCompatActivity {


    private DiskLruCache diskLruCache;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main7);
        String url="http://f.hiphotos.baidu.com/image/pic/item/b7fd5266d016092446517fdadd0735fae7cd34ff.jpg";
        String key="abc";
        String key2="adfafafadf";
        String key3="zzzzzzzzzz";
        try {
            diskLruCache=getDiskLruCache("testDiskLruCache");
//            saveDiskData(diskLruCache,key,key.getBytes());
//            saveDiskData(diskLruCache,key2,key2.getBytes());
//            saveDiskData(diskLruCache,key3,key3.getBytes());
//            System.out.println(new String(getDiskData(diskLruCache,key)));
//            System.out.println(new String(getDiskData(diskLruCache,key2)));
//            System.out.println(new String(getDiskData(diskLruCache,key3)));
//            removeDiskData(diskLruCache,key);
//            removeDiskData(diskLruCache,key2);
//            removeDiskData(diskLruCache,key3);
//            clearDiskData(diskLruCache);
            System.out.println(getDiskDataSize(diskLruCache));
            System.out.println(diskLruCache.getMaxSize());
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
//获取DiskLruCache对象,第一次参数为文件路径名
    public DiskLruCache getDiskLruCache(String fileDirectory) throws IOException {
        long size=1024*1024*10;//10MB
        DiskLruCache diskLruCache = null;
        File diskCacheFile=new File(getCacheDir(),fileDirectory);
        if (!diskCacheFile.exists()){
            diskCacheFile.mkdir();
        }
        diskLruCache=DiskLruCache.open(diskCacheFile, 1,1,size);
        return diskLruCache;
    }
//根据key保存byte[] data数据
    public void saveDiskData(final DiskLruCache diskLruCache, final String key, final byte[] data) {
        new Thread(new Runnable() {
            @Override
            public void run() {
                try {
                    DiskLruCache.Editor editor = null;
                    editor=diskLruCache.edit(key);
                    OutputStream outputStream=null;
                    if (editor!=null){
                        outputStream=editor.newOutputStream(0);
                        if (outputStream!=null){
                            outputStream.write(data);
                            outputStream.close();
                            editor.commit();
                        }
                    }
                    diskLruCache.flush();
                    System.out.println("data大小: "+data.length);
                    System.out.println("DiskLruCache大小: "+diskLruCache.size());
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }).start();
    }
//根据key获取byte[]数据
    public byte[] getDiskData(DiskLruCache diskLruCache, String key) throws IOException {
        DiskLruCache.Snapshot snapshot=diskLruCache.get(key);
        System.out.println(snapshot.getLength(0));
        InputStream inputStream= snapshot.getInputStream(0);
        ByteArrayOutputStream byteArrayOutputStream=new ByteArrayOutputStream();
        byte[] b=new byte[1024];
        int len=0;
        while ((len=inputStream.read(b))!=-1){
            byteArrayOutputStream.write(b,0,len);
        }
        byteArrayOutputStream.flush();
        inputStream.close();
        return byteArrayOutputStream.toByteArray();
    }
//清除指定key的数据
    public void removeDiskData(DiskLruCache diskLruCache, String key) throws IOException {
        diskLruCache.remove(key);
        diskLruCache.flush();
    }
//清空数据
    public void clearDiskData(DiskLruCache diskLruCache) throws IOException {
        diskLruCache.delete();
    }
//获取缓存大小
    public long getDiskDataSize(DiskLruCache diskLruCache){
        return diskLruCache.size();
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();
        try {
            diskLruCache.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

 

 

一个完整的网络请求+二级缓存的Bitmap图片加载轮子(自己写的只实现了基本功能,非常粗糙)

https://github.com/18668197127/ImageLoader/tree/master

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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值