[Android开发]三级缓存初探索

三级缓存:
内存缓存:优先加载,速度最快
本地内存:速度其次,内存没有,读本地
网络缓存:速度最慢,本地也没有,才访问网络

我们定义一个图片加载类:
MyBitmapUtils.java

/**
 * 自定义图片加载工具
 * @author dream
 *
 */
public class MyBitmapUtils {

    NetCacheUtils mNetCacheUtils;
    LocalCacheUtils mLocalCacheUtils;
    MemoryCacheUtils mMemoryCacheUtils;

    public MyBitmapUtils() {
        mMemoryCacheUtils = new MemoryCacheUtils();
        mLocalCacheUtils = new LocalCacheUtils();
        mNetCacheUtils = new NetCacheUtils(mLocalCacheUtils,mMemoryCacheUtils);

    }

    public void display(ImageView ivPic, String url) {
        ivPic.setImageResource(R.drawable.news_pic_default);
        Bitmap bitmap = null;
        bitmap = mMemoryCacheUtils.getBitmapFromMemory(url);
        if(bitmap != null)
        {
            ivPic.setImageBitmap(bitmap);
            return;
        }
        //从本地读
        bitmap = mLocalCacheUtils.getBitmapFromLocal(url);
        if(bitmap != null)
        {
            ivPic.setImageBitmap(bitmap);
            mMemoryCacheUtils.setBitmapToMemory(url, bitmap);   //将图片保存在内存
            return;
        }
        //从过网络读
        mNetCacheUtils.getBitmapFromNet(ivPic, url);
    }

}

从网络获取的类:
NetCacheUtils.java

/**
 * 网络缓存
 * @author dream
 *
 */
public class NetCacheUtils {

    private HttpURLConnection conn = null;
    private LocalCacheUtils mLocalCacheUtils;
    private MemoryCacheUtils mMemoryCacheUtils;
    public NetCacheUtils(LocalCacheUtils mLocalCacheUtils, MemoryCacheUtils mMemoryCacheUtils) {
        this.mLocalCacheUtils = mLocalCacheUtils;
        this.mMemoryCacheUtils = mMemoryCacheUtils;
    }

    /**
     * 从网络下载图片
     * @param ivPic
     * @param url
     */
    public void getBitmapFromNet(ImageView ivPic, String url) {
        new BitmapTask().execute(ivPic, url);  //启动 AsyncTask
    }

    class BitmapTask extends AsyncTask<Object, Void, Bitmap>
    {
        private ImageView ivPic;
        private String url;

        /**
         * 耗时方法在此形成,子线程
         */

        @Override
        protected Bitmap doInBackground(Object... params) {
            ivPic = (ImageView) params[0];
            url = (String) params[1];
            ivPic.setTag(url);
            return downloadBitmap(url);
        }

        /**
         * 更新进度,主线程
         */
        @Override
        protected void onProgressUpdate(Void... values) {
            super.onProgressUpdate(values);
        }

        /**
         * 耗时方法结束后,执行该方法,主线程
         */
        @Override
        protected void onPostExecute(Bitmap result) {
            if(result != null)
            {
                String bindUrl = (String) ivPic.getTag();
                if(url.equals(bindUrl))
                {
                    //确保图片设置了正确的ImageView
                    ivPic.setImageBitmap(result);
                    //将图片保存在本地
                    mLocalCacheUtils.setBitmapToLocal(url, result);
                    // 将图片保存在内存
                    mMemoryCacheUtils.setBitmapToMemory(url, result);
                }

            }

        }

    }

    /**
     * 下载图片
     * @param url
     * @return
     */
    private Bitmap downloadBitmap(String url)
    {
        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 inputStream = conn .getInputStream();
                //图片压缩
                BitmapFactory.Options options = new BitmapFactory.Options();
                options.inSampleSize = 2;//宽高都压缩为原来的1/2
                options.inPreferredConfig = Bitmap.Config.RGB_565;
                Bitmap bitmap = BitmapFactory.decodeStream(inputStream,null, options);
                return bitmap;
            }

        } catch (MalformedURLException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        finally {
            conn.disconnect();
        }
        return null;
    }

}

从本地获取的类:
LocalCacheUtils.java

/**
 * 本地缓存
 * @author dream
 *
 */
public class LocalCacheUtils {

    public static final String CACHE_PATH = Environment.getExternalStorageDirectory().
            getAbsolutePath() + "/beijingwisdom";
    /**
     * 从本地sdcard读图片
     * @param url
     */
    public Bitmap getBitmapFromLocal(String url)
    {
        try {
            String fileName = MD5Encoder.encode(url);
            File file = new File(CACHE_PATH,fileName);
            if(file.exists())
            {
                Bitmap bitmap = BitmapFactory.decodeStream(new FileInputStream(file));
                return bitmap;
            }
        } catch (Exception e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        return null;
    }
    /**
     * 向sdcard写图片
     */
    public void setBitmapToLocal(String url,Bitmap bitmap)
    {
        try {
            String fileName = MD5Encoder.encode(url);
            File file = new File(CACHE_PATH,fileName);
            File parentFile = file.getParentFile();
            if(!parentFile.exists())
            {
                parentFile.mkdirs();
            }

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

从内存获取的类:
MemoryCacheUtils.java

/**
 * 内存缓存
 * 
 * @author dream
 *
 */
public class MemoryCacheUtils {

    // public HashMap<String, SoftReference<Bitmap>> mMemoryCache = new
    // HashMap<String, SoftReference<Bitmap>>();
    public 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;
            }
        };
    }

    /**
     * 从内存读
     * 
     * @param url
     */
    public Bitmap getBitmapFromMemory(String url) {
        // SoftReference<Bitmap> softReference = mMemoryCache.get(url);
        // if(softReference != null)
        // {
        // Bitmap bitmap = softReference.get();
        // return bitmap;
        // }
        return mMemoryCache.get(url);


    }

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

内存溢出问题:
Android默认每个app只能分配16M的内存,所以经常在内存中加载图片会发生内存溢出,我们来熟悉一下Java中的引用:

强引用:垃圾回收器不会回收,Java默认引用都是强引用
软引用:SoftReference 在内存不够时,Java垃圾回收会考虑回收
弱引用:WeakReference 在内存不够时,Java垃圾回收会优先回收
虚引用:PhantomReference 在内存不够时,Java垃圾回收会最优先回收

在Android2.3+,系统会优先将SoftReference的对象提前回收,即使内存够用,所以不再使用,所以这个我们也不能用了。

接下来介绍LruCache:
least recentlly use 最近最少未使用
会将内存控制在一定的大小内,超出最大值时会自动回收,这个最大值开发者自己定。
对于界面中可以缩放的图片我们也可以进行图片压缩。

InputStream inputStream = conn .getInputStream();
                //图片压缩
                BitmapFactory.Options options = new BitmapFactory.Options();
                options.inSampleSize = 2;//宽高都压缩为原来的1/2
                options.inPreferredConfig = Bitmap.Config.RGB_565;
                Bitmap bitmap = BitmapFactory.decodeStream(inputStream,null, options);
                return bitmap;
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值