Android 三级缓存

三级缓存简介

·内存缓存:优先加载,速度最快

·文件缓存:次之加载,速度次之

·网络缓存:最次加载,速度最慢,浪费流量

简单原理图

这里写图片描述

首先从内存缓存获取,其次再从文件缓存获取,最后从网络缓存获取。
从网络缓存获取后,同时保存到文件缓存和内存缓存,以便下次获取。

内存溢出OOM


android默认给每个app只分配16M的内存。
java中的引用
强引用 垃圾回收器不会回收,java默认引用都是强引用
软引用 SoftReference 在内存不够时,会考虑回收
弱引用 WeakReference 在内存不够时,会优先回收
虚引用 PhantomReference 在内存不够时,最优先回收


LruCache和DisLruCache两个类,分别用于内存和硬盘缓存。核心思想是当缓存空间满了之后,会删除最近最少使用的缓存。

内存缓存代码

LruCache

LruCache的原理是将缓存对象作为强引用,保存在LinkedHashMap中,当缓存满了之后,将对象从Map中移除,重新通过put方法添加新的缓存,get方法获取缓存。

LruCache的核心思想就是维护一个缓存对象的队列,该队列由LinkedHashMap维护。一直没访问的对象放在队尾,最新访问的放在队首,当队列满了之后,从队尾开始淘汰,队首的最后淘汰。

package com.seaicelin.bitmaputils;

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


public class MemoryCacheUtils {

    private LruCache<String, Bitmap> mMemoryCache;

    public MemoryCacheUtils() {
        //最大内存的八分之一
        long memoryMax = Runtime.getRuntime().maxMemory() / 8;
        mMemoryCache = new LruCache<String, Bitmap>((int) memoryMax) {
            @Override
            protected int sizeOf(String key, Bitmap value) {
                int byteCount = value.getRowBytes() * value.getHeight();
                return byteCount;
            }
        };
    }

    /**
     * 从内存读
     * 
     * @param url
     */
    public Bitmap getBitMapFromMemory(String url) {
        return mMemoryCache.get(url);
    }

    /**
     * 写内存
     * 
     * @param url
     * @param bitmap
     */
    public void setBitmapToMemory(String url, Bitmap bitmap){
        mMemoryCache.put(url, bitmap);
    }
}

文件缓存代码

package com.seaicelin.bitmaputils;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.os.Environment;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;


public class LocalCacheUtils {

    private static final String CACHE= "/cache";
    public static final String CACHE_PATH = Environment.getDownloadCacheDirectory().getAbsolutePath()
            + CACHE;

    //从本地SD卡获取图片
    public Bitmap getBitmapFromLocal(String url){
        String fileName = Md5Encoder.encode(url);
        File file = new File(CACHE_PATH, fileName);

        if(file.exists()){
            try {
                Bitmap bitmap = BitmapFactory.decodeStream(new FileInputStream(file));
                return bitmap;
            } catch (FileNotFoundException e) {
                e.printStackTrace();
            }
        }
        return null;
    }

    //向SD卡保存图片
    public void setBitmapToLocal(String url, Bitmap bitmap){
        String fileName = MD5Encoder.encode(url);
        File file = new File(CACHE_PATH, fileName);
        File parentFile = file.getParentFile();
        if(!parentFile.exists()){//如果文件夹不存在,创建文件夹
            parentFile.mkdirs();
        }
        //将图片保存在本地
        try {
            bitmap.compress(Bitmap.CompressFormat.JPEG, 100, new FileOutputStream(file));
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        }
    }
}

网络缓存代码

package com.seaicelin.bitmaputils;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.os.AsyncTask;
import android.widget.ImageView;
import java.io.IOException;
import java.io.InputStream;
import java.net.HttpURLConnection;
import java.net.URL;

public class NetCacheUtils {

    private MemoryCacheUtils memoryCacheUtils;
    private LocalCacheUtils localCacheUtils;


    public NetCacheUtils(MemoryCacheUtils memoryCacheUtils, LocalCacheUtils localCacheUtils){
        this.localCacheUtils = localCacheUtils;
        this.memoryCacheUtils = memoryCacheUtils;
    }

    //从网络下载图片
    public void getBitmapFromNet(ImageView imageView, String url){
        new BitmapTask().execute(imageView, url);
    }

    private class BitmapTask extends AsyncTask<Object, Void, Bitmap> {

        private ImageView image;
        private String url;

        @Override
        protected Bitmap doInBackground(Object... params) {
            image = (ImageView) params[0];
            url = (String) params[1];

            image.setTag(url);//must called from UI thread

            return downloadBitmap(url);
        }

        @Override
        protected void onPostExecute(Bitmap bitmap) {
            if(bitmap != null){
                String bindUrl = (String) image.getTag();
                if(url.equals(bindUrl)){
                    image.setImageBitmap(bitmap);
                    setBitmapToLocalAndMemory(url, bitmap);
                }
            }
        }

        @Override
        protected void onProgressUpdate(Void... values) {
            super.onProgressUpdate(values);
        }
    }

    private Bitmap downloadBitmap(String url) {
        HttpURLConnection conn = null;
        try {
            conn = (HttpURLConnection) new URL(url).openConnection();
            conn.setConnectTimeout(5000);
            conn.setReadTimeout(5000);
            conn.setRequestMethod("GET");
            conn.connect();
            int responseCode = conn.getResponseCode();
            if(responseCode == 200){
                InputStream in =  conn.getInputStream();
                //图片压缩处理
                BitmapFactory.Options option= new BitmapFactory.Options();
                option.inSampleSize = 2;//宽高压缩为原来的1/2,
                option.inPreferredConfig = Bitmap.Config.RGB_565;//设置图片的格式
                Bitmap bitmap = BitmapFactory.decodeStream(in, null, option);
                return bitmap;
            }
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            conn.disconnect();
        }
        return null;
    }

    //把下载好的图片保存到内存和本地
    public void setBitmapToLocalAndMemory(String url, Bitmap bitmap){
        memoryCacheUtils.setBitmapToMemory(url, bitmap);
        localCacheUtils.setBitmapToLocal(url, bitmap);
    }
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值