简述安卓中的三级缓存机制

Android应用中联网加载并显示图片时,为了用户体验和节省流量,一定用到图片的缓存

关于三级缓存的理解可以分为:

  1. 内存缓存(物理空间的缓存)
  2. 本地缓存(java对象的缓存)
  3. 网络缓存

首先为大家介绍一个现在比较成熟应用也比较广泛的第三方开源的工具类 xUtils系列之BitmapUtils

接下来我们将通过自己的代码为大家分析BitmapUtils实现图片加载等一系列工作的原理

  • 第一步:创建三个类NetCacheUtils(用于网络缓存)
    LocalCacheUtils(用于本地缓存)
    MemoryCacheUtils(用于内存缓存)
  • 第二步:创建MyBitmapUtils类,用于处理用户加载图片的请求

创建本地缓存类LocalCacheUtils:

public class LocalCacheUtils {
    public static final String CACHE_PATH = Environment
            .getExternalStorageDirectory().getAbsolutePath() + "/zhwh";



    public Bitmap getBitmap(String url) {
        String fiaeneme;
        try {
            fiaeneme = MD5Encoder.encode(url);
            File file = new File(CACHE_PATH, fiaeneme);
            if(file.exists()){
                Bitmap bitmap=BitmapFactory.decodeStream(new FileInputStream(file));
                System.out.println("内地缓存执行。。。。。。");
                return bitmap;
            }
        }
        catch (Exception e) {       
            e.printStackTrace(); 
        }

        return null;

    }

    /**
     * 
     * @param @param url
     * @param @param bitmap
     * @return void
     */
    public void setBitmap(String url, Bitmap bitmap) {
        try {
            String fiaeneme = MD5Encoder.encode(url);
            File file = new File(CACHE_PATH, fiaeneme);
            File parentFile = file.getParentFile();
            if (!parentFile.exists()) {// 如果文件夹不存在, 创建文件夹
                parentFile.mkdirs();
            }

            // 将图片保存在本地
            bitmap.compress(CompressFormat.JPEG, 100,
                    new FileOutputStream(file));
        } catch (Exception e) {

            e.printStackTrace();
        }
    }
}

对LocalCacheUtils的解释说明:

主要的两个方法:setBitmap(String url, Bitmap bitmap)和getBitmap(String url)

  1. setBitmap(String url, Bitmap
    bitmap):以经过处理后的url为文件名在内存中创建一个文件,然后将传入的Bitmap 对象写入这个文件当中去
  2. getBitmap(String url) :以相同的方式处理url作为文件名在内存中读取文件中的BitMap对象并返回

创建内存缓存类MemoryCacheUtils:

public class MemoryCacheUtils {
    private LruCache<String, Bitmap> mMemoryCache;

    public MemoryCacheUtils() {
        long maxMemory = Runtime.getRuntime().maxMemory() / 8;// 模拟器默认是16M
        mMemoryCache = new LruCache<String, Bitmap>((int) maxMemory) {
            @Override
            protected int sizeOf(String key, Bitmap value) {
                int byteCount = value.getRowBytes() * value.getHeight();// 获取图片占用内存大小
                return byteCount;
            }
        };
    }

    public Bitmap getBitmap(String url) {
        return mMemoryCache.get(url);
    }

    public void setBitmap(String url, Bitmap bitmap) {
        mMemoryCache.put(url, bitmap);
    }
}

关于LruCache的说明:LruCache是android提供的一个缓存工具类,其算法是最近最少使用算法。它把最近使用的对象用“强引用”存储在LinkedHashMap中,并且把最近最少使用的对象在缓存值达到预设定值之前就从内存中移除。关于LruCache的详细说明

创建网络缓存类:NetCacheUtils

public class NetCacheUtils {
    LocalCacheUtils utils1;
    MemoryCacheUtils utils2;

    public NetCacheUtils(LocalCacheUtils utils1, MemoryCacheUtils utils2) {
        this.utils1 = utils1;
        this.utils2 = utils2;
    }

    public void getBitmapFromNet(ImageView iv, String url) {
        new BitmapTask().execute(iv, url);
    }

    /**
     * 异步下载
     * 
     * @author 直到世界尽头
     * 
     */
    class BitmapTask extends AsyncTask<Object, Void, Bitmap> {

        private ImageView iv;
        private String url;

        /**
         * 子线程进行
         * 
         * @param @param arg0
         * @param @return
         * @return Bitmap 返回下载得到的数据结果
         */
        @Override
        protected Bitmap doInBackground(Object... parms) {
            iv = (ImageView) parms[0];
            url = (String) parms[1];
            iv.setTag(url);// 将url和imageview绑定
            return downloadbitmap(url);
        }

        @Override
        protected void onProgressUpdate(Void... values) {

            super.onProgressUpdate(values);
        }

        /**
         * 下载完成之后执行
         */
        @Override
        protected void onPostExecute(Bitmap result) {
            super.onPostExecute(result);

            String bindurl = (String) iv.getTag();
            if (bindurl.equals(url)) {
                iv.setImageBitmap(result);
            }

            // 加载到本地内存
            utils1.setBitmap(url, result);
            // 加载到缓存内存
            utils2.setBitmap(url, result);
            System.out.println("网络获取图片。。。。");
        }
    }

    private Bitmap downloadbitmap(String url) {
        HttpURLConnection connection = null;
        try {
            URL u = new URL(url);
            connection = (HttpURLConnection) u.openConnection();
            connection.setRequestMethod("GET");
            connection.setConnectTimeout(5000);
            connection.setReadTimeout(5000);
            connection.connect();
            if (connection.getResponseCode() == 200) {
                InputStream is = connection.getInputStream();
                // 图片压缩处理
                BitmapFactory.Options option = new BitmapFactory.Options();
                option.inSampleSize = 2;// 宽高都压缩为原来的二分之一, 此参数需要根据图片要展示的大小来确定
                option.inPreferredConfig = Bitmap.Config.RGB_565;// 设置图片格式

                Bitmap bitmap = BitmapFactory.decodeStream(is, null,option);
                return bitmap;
            }

        } catch (Exception e) {

            e.printStackTrace();
        } finally {
            connection.disconnect();
        }

        return null;
    }
}

说明:关于这个类中用到的一步加载可见另一篇博客异步加载详解

最后创建MyBitmapUtils类用于协调调用前面的三个缓存类:

public class MyBitmapUtils {
    NetCacheUtils netcacheutils;
    LocalCacheUtils localcacheutils;
    MemoryCacheUtils memorycacheutils;

    public MyBitmapUtils() {
        localcacheutils = new LocalCacheUtils();
        memorycacheutils = new MemoryCacheUtils();
        this.netcacheutils = new NetCacheUtils(localcacheutils,
                memorycacheutils);
    }

    /**
     * 三级缓存
     * 
     * @param @param iv
     * @param @param url
     * @return void
     */
    public void Display(ImageView iv, String url) {
        Bitmap map;
        //内存缓存
        map = memorycacheutils.getBitmap(url);
        if (map != null) {
            iv.setImageBitmap(map);
            return;
        }

        // 本地缓存
        map = localcacheutils.getBitmap(url);
        if (map != null) {
            memorycacheutils.setBitmap(url, map);
            iv.setImageBitmap(map);
            return;
        }

        // 网络缓存
        netcacheutils.getBitmapFromNet(iv, url);
    }
}

三级缓存调用流程

猜你喜欢

转载自blog.csdn.net/xikai18827083487/article/details/52959091