android图片三级缓存

本文介绍了Android中实现图片三级缓存的机制。通过一个读取图片的工具类,详细阐述了如何从内存、本地缓存和网络逐级加载图片,并在加载过程中将图片缓存至不同级别,确保高效加载和用户体验。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

**这只是一个android图片三级缓存的原理,是我从视频学到的,也是我自己整理一下,应对面试用的。真正用的话建议还是使用xutils.
建议把下面的四个类的代码看一遍,对理解三级缓存有帮助**
这里是一个自定义的图片工具类
public class MyBitmapUtils {
    NetCacheUtils mNetCacheUtils;//网络图片工具
    LocalCacheUtils mLocalCacheUtils;//本地图片工具类
    MemoryCacheUtils memoryCacheUtils;//内存图片工具类

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

    }

    //加载图片的方法
    public void display(ImageView ivPic, String url) {
        ivPic.setImageResource(R.drawable.news_pic_default);//设置加载默认图片
        Bitmap bitmap=null  ;

        //先从从内存中读去图片
        bitmap=memoryCacheUtils.getBitmapFromMemory(url);
        if(bitmap!=null){
            ivPic.setImageBitmap(bitmap);
            return ;
        }
        //从本地sd卡中读去图片
        bitmap=mLocalCacheUtils.getBitmapFromLocal(url);
        if(bitmap!=null){
        //如果读到了图片
            ivPic.setImageBitmap(bitmap);
            memoryCacheUtils.setBitmaptoMemory(url, bitmap);//将图片保存在内存中
        return;
        }
        //从网络中读去图片
        mNetCacheUtils.getBitmapFormNet(ivPic, url);
    }
}

接下来是三个读取图片工具类

/*从网络读取图片*/
public class NetCacheUtils {
    private LocalCacheUtils mlocalCacheUtils;//本地
    private MemoryCacheUtils mMemoryCacheUtils;//内存

    public NetCacheUtils(LocalCacheUtils localCacheUtils,
            MemoryCacheUtils memoryCacheUtils) {
        mlocalCacheUtils = localCacheUtils;
        mMemoryCacheUtils = memoryCacheUtils;
    }

    // 从网络下载图片
    public void getBitmapFormNet(ImageView ivPic, String url) {
        new BitmapTask().execute(ivPic, url);//启动AsyncTask,参数会在doInbackground中获取 会调用下面的doInBackground(Object... params)等等方法。这可以看作是一个启动方法
    }

    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);// 将url和imageview绑定
            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.setBitmapTocal(url, result);//将图片保存到本地
                    mMemoryCacheUtils.setBitmaptoMemory(url, result);// 将图片保存在内存
                    System.out.println("从网络缓存读取图片了");

                }

            }
            super.onPostExecute(result);
        }
    }

    // 从网络下载图片
    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 inputStram = conn.getInputStream();

                // 图片压缩处理
                BitmapFactory.Options option = new BitmapFactory.Options();
                option.inSampleSize = 2;// 宽高都压缩为原来的二分之一,此参数需要根据图片要展示的大小来确定
                option.inPreferredConfig = Bitmap.Config.RGB_565;// 设置图片格式
                Bitmap bitmap = BitmapFactory.decodeStream(inputStram, null,
                        option);

                return bitmap;
            }

        } catch (Exception e) {

            e.printStackTrace();
        } finally {

            conn.disconnect();
        }
        return null;

    }

}

本地缓存类

//本地缓存
 class LocalCacheUtils {

     public  static final String CACHE_PATH=Environment.getExternalStorageDirectory().getAbsolutePath()+"/zhbj_cache_52";//图片存到sd卡中的地址
    // 从本地sdcard读图片
    public Bitmap getBitmapFromLocal(String url) {
     try{
     //存的时候把图片的的地址用MD5加密后作为存储的名字,所以取得时候也要把地址加密。
        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){

        e.printStackTrace(); 
     }
        return null;
    }

    // 向sdcard写图片
    public void setBitmapTocal(String url,Bitmap bitmap) {
        String filename;
        try {
            filename = MD5Encoder.encode(url);
            File file=new File(CACHE_PATH, filename);
            File parentFile=file.getParentFile();
            if(!parentFile.exists()){
                //如果文件夹不存在,创建文件夹
                parentFile.mkdir();
                //将图片保存在本地
                bitmap.compress(CompressFormat.JPEG, 100,
                        new FileOutputStream(file));
            }
        } catch (Exception e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
    }
}

内存缓存

public class MemoryCacheUtils {
    // private HashMap<String , SoftReference<Bitmap>> mMemoryCache=new
    // HashMap<String, SoftReference<Bitmap>>();


/*异步加载图片的例子,网上也比较多,大部分用了HashMap<String, SoftReference<Drawable>> imageCache ,但是现在已经不再推荐使用这种方式了,因为从 Android 2.3 (API Level 9)开始,垃圾回收器会更倾向于回收持有软引用或弱引用的对象,这让软引用和弱引用变得不再可靠。另外,Android 3.0 (API Level 11)中,图片的数据会存储在本地的内存当中,因而无法用一种可预见的方式将其释放,这就有潜在的风险造成应用程序的内存溢出并崩溃,所以我这里用得是LruCache来缓存图片,当存储Image的大小大于LruCache设定的值,系统自动释放内存,这个类是3.1版本中提供的,如果你是在更早的Android版本中开发,则需要导入android-support-v4的jar包(这里要注意咯)*/

    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 getBitmapFromMemory(String url) {
        // 防止内存溢出,但下面的方法实际中不用
        // SoftReference<Bitmap> softReference=mMemoryCache.get(url);
        // if(softReference!=null){
        // Bitmap bitmap=softReference.get();
        // return bitmap;
        //
        //
        // }
        return mMemoryCache.get(url);

    }

    // 写内存
    public  void setBitmaptoMemory(String url, Bitmap bitmap) {
        // SoftReference<Bitmap> softReference = new
        // SoftReference<Bitmap>(bitmap);
        // mMemoryCache.put(url, softReference);
        mMemoryCache.put(url, bitmap);
    }
}

调用举例
private MyBitmapUtils myutils;
myutils.display(holder.ivPic,item.listimage );

//注释 自己的bitmaoutils
//注释 holder.ivPic 一个holder中的imgivew.
//注释 item.listimage 一个图片的地址
只需知道两个参数一个是imageivew,一个是url就行

首先会从内存中找图片,内存中没有,会在从本地sd卡中读取,如果从本地找到图片,会显示到imgview中,然后顺便存到内存中,如果没有在从网络中读取,从网络中读到流后,生成bitmap 顺便存到内存与sd卡中。




  我只是一个菜鸟,视频里就是这么讲的,怎么实际中要用的话,建议用xutils,因为三级缓存它帮你实现了。


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值