android 三级缓存 简介

三级缓存简介

  • 内存缓存:优先加载,速度最快
  • 文件缓存:次之加载,速度次之
  • 网络缓存:最次加载,速度最慢,浪费流量

简单原理图

这里写图片描述

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


内存溢出OOM

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

注意,android2.3+,系统会优先将SoftReference回收,即使内存足够用。详见 博文:
Android 图片三级缓存之内存缓存(告别软引用(SoftRefrerence)和弱引用(WeakReference))
http://blog.csdn.net/fancylovejava/article/details/25705169


LruCache

  • Least recently use 最少最近使用
  • 将内存控制在一定范围内,超出最大值能够自动回收,最大值由开发者设定

内存缓存代码

package com.seaicelin.bitmaputils;

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

/**
 * Created by linhai on 16/8/2.
 */
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;

/**
 * Created by linhai on 16/8/2.
 */
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;

/**
 * Created by linhai on 16/8/2.
 */
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);
    }
}

总结

本篇的目的是了解三级缓存的基本原理。然而上面的代码不完善,不能运用到实际项目中。现在我们更多的是采用Github上的现有开源框架来运用到我们的项目,稳定又高效,避免重复造轮子。

网络加载的开源框架比如:
Xutils:https://github.com/wyouflf/xUtils
Okhttp: https://github.com/square/okhttp
Picasso: https://github.com/square/picasso
Retrofit: https://github.com/square/retrofit
更多相关的开源框架 工具篇可以参照一下连接:
http://www.trinea.cn/android/android-open-source-projects-dev-lib/

  • 4
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值