利用listview 进行图片三级缓存

需要导入一个implementation 'com.jakewharton:disklrucache:2.0.2' 


package jiyun.com.demodisklrucache2.adapter;



import android.content.Context;
import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.os.AsyncTask;
import android.os.Environment;
import android.util.Log;
import android.util.LruCache;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.BaseAdapter;
import android.widget.ImageView;
import android.widget.TextView;


import com.jakewharton.disklrucache.DiskLruCache;


import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileDescriptor;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.HttpURLConnection;
import java.net.URL;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.List;


import jiyun.com.demodisklrucache2.R;
import jiyun.com.demodisklrucache2.beans.InteractiveBean;


public class MyAdapter extends BaseAdapter {
    private Context mContext;
    private List<InteractiveBean> mList;
    private LruCache lruCache;
    private DiskLruCache diskLruCache;
    private int sizeOf = 0;


    public MyAdapter(Context mContext, List<InteractiveBean> mList) {
        this.mContext = mContext;
        this.mList = mList;
        sizeOf = (int) ((Runtime.getRuntime().maxMemory() / 1024) / 8);
        lruCache = new LruCache<String, Bitmap>(sizeOf) {
            @Override
            protected int sizeOf(String key, Bitmap value) {
                return value.getByteCount() / 1024;
            }
        };
        File photo = getDiskCacheDir(mContext, "photo");
        if (!photo.exists()) {
            photo.mkdirs();
        }
        try {
            diskLruCache = DiskLruCache.open(photo, getAppVersion(mContext), 1, 10 * 1024 * 1024);
        } catch (IOException e) {
            e.printStackTrace();
        }
    }


    @Override
    public int getCount() {
        return mList.size();
    }


    @Override
    public Object getItem(int position) {
        return mList.get(position);
    }


    @Override
    public long getItemId(int position) {
        return position;
    }


    @Override
    public View getView(int position, View convertView, ViewGroup parent) {
        ViewHolder holder = null;
        if (convertView == null) {
            holder = new ViewHolder();
            convertView = LayoutInflater.from(mContext).inflate(R.layout.list_view, null);
            holder.mText = convertView.findViewById(R.id.tv_title);
            holder.mImageView = convertView.findViewById(R.id.image_first);
            convertView.setTag(holder);
//            convertView.setTag(position);
        } else {
            holder = (ViewHolder) convertView.getTag();
        }
        holder.mText.setText(mList.get(position).getTitle());
        //设置图片为不可见状态
        holder.mImageView.setImageResource(R.mipmap.ic_launcher);
        holder.mImageView.setVisibility(View.INVISIBLE);
        //防止错位
        holder.mImageView.setTag(mList.get(position));
        LoadImage loadImage = new LoadImage(holder);
        loadImage.execute(mList.get(position).getImage());
        holder.mImageView.setTag(mList.get(position).getImage());
        //holder.c.setTag(position);
        return convertView;
    }


    class LoadImage extends AsyncTask<String, Integer, Bitmap> {
        Bitmap bitmap = null;
        InputStream is = null;
        String url = null;
        ViewHolder holder = null;
        DiskLruCache.Snapshot snapshot = null;
        FileInputStream fileInputStream = null;
        FileDescriptor fileDescriptor = null;
        BufferedInputStream in = null;
        BufferedOutputStream out = null;
        public LoadImage(ViewHolder holder) {
            this.holder = holder;
        }
        @Override
        protected Bitmap doInBackground(String... strings) {
            try {
                url = strings[0];
                Bitmap cachebitmap = getBitmapFromCache(url);
                //先从缓存中取,如果缓存不为空,则返回图片
                if (cachebitmap != null) {
                    Log.e(url, "存在于内存中,直接返回");
                    return cachebitmap;
                } else {


                    //如果内存缓存中取不到,再尝试从硬盘中取
                    Log.e(url, "内存中不存在,从硬盘缓存中找");
                    snapshot = diskLruCache.get(hashKeyForDisk(url));
                    //如果snapshot为空,则从网络下载图片
                    if (snapshot == null) {
                        Log.e(url, "硬盘中没有,从网络下载");
                        URL url_image = new URL(url);
                        HttpURLConnection conn = (HttpURLConnection) url_image.openConnection();
                        conn.setDoInput(true);
                        conn.connect();
                        //利用editor将图片写入硬盘缓存
                        is = conn.getInputStream();
                        in = new BufferedInputStream(is, 8 * 1024);
                        DiskLruCache.Editor editor = diskLruCache.edit(hashKeyForDisk(url));
                        OutputStream outputStream = editor.newOutputStream(0);
                        out = new BufferedOutputStream(outputStream, 8 * 1024);
                        int b;
                        while ((b = in.read()) != -1) {
                            out.write(b);
                        }
                        editor.commit();
                        diskLruCache.flush();
                        conn.disconnect();
                        out.close();
                        in.close();
                    }
                    //再次查找对应缓存
                    snapshot = diskLruCache.get(hashKeyForDisk(url));
                    //将bitmap写入内存缓存
                    fileInputStream = (FileInputStream) snapshot.getInputStream(0);
                    fileDescriptor = fileInputStream.getFD();
                    //如果fileDescriptor不为空,开始解析bitmap,加入到内存缓存中,并返回图片
                    if (fileDescriptor != null) {
                        Bitmap diskcachebitmap = BitmapFactory.decodeFileDescriptor(fileDescriptor);
                        if (diskcachebitmap == null) {
                            return null;
                        } else {
                            Log.e(url, "重新加入到内存缓存中");
                            addBitmapToCache(url, diskcachebitmap);
                            return diskcachebitmap;
                        }
                    }
                    return bitmap;


                }
            } catch (IOException e) {
                e.printStackTrace();
            }
            return null;
        }


        @Override
        protected void onPostExecute(Bitmap bitmap) {
            ImageView mImageView = holder.mImageView;
            if (mImageView.getTag().equals(url)) {
                mImageView.setVisibility(View.VISIBLE);
                mImageView.setImageBitmap(bitmap);
            }
            super.onPostExecute(bitmap);
        }
    }


    public class ViewHolder {
        private TextView mText;
        private ImageView mImageView;
    }


    //这是获取文件写在哪里的方法
    public File getDiskCacheDir(Context context, String uniqueName) {
        String cachePath;
        if (Environment.MEDIA_MOUNTED.equals(Environment.getExternalStorageState()) || !Environment.isExternalStorageRemovable()) {
            cachePath = context.getExternalCacheDir().getPath();
        } else {
            cachePath = context.getCacheDir().getPath();
        }
        return new File(cachePath + File.separator + uniqueName);
    }


    //这是获取应用版本号的方法
    public int getAppVersion(Context context) {
        try {
            PackageInfo info = context.getPackageManager().getPackageInfo(context.getPackageName(), 0);
            return info.versionCode;
        } catch (PackageManager.NameNotFoundException e) {
            e.printStackTrace();
        }
        return 1;
    }


    //将url进行MD5编写
    public String hashKeyForDisk(String key) {
        String cacheKey;
        try {
            //信息摘要算法提供类
            final MessageDigest mDigest = MessageDigest.getInstance("MD5");
            mDigest.update(key.getBytes());
            cacheKey = bytesToHexString(mDigest.digest());
        } catch (NoSuchAlgorithmException e) {
            cacheKey = String.valueOf(key.hashCode());
        }
        return cacheKey;
    }


    private String bytesToHexString(byte[] bytes) {
        StringBuilder sb = new StringBuilder();
        for (int i = 0; i < bytes.length; i++) {
            //十六进制转换
            String hex = Integer.toHexString(0xFF & bytes[i]);
            if (hex.length() == 1) {
                sb.append('0');
            }
            sb.append(hex);
        }
        return sb.toString();
    }


    public void addBitmapToCache(String key, Bitmap bitmap) {
        if (getBitmapFromCache(key) == null) {
            if (bitmap == null) {
                return;
            } else {
                lruCache.put(key, bitmap);
            }
        }


    }


    public Bitmap getBitmapFromCache(String key) {


        return (Bitmap) lruCache.get(key);
    }
}
/*//上下文对象
    private Context mContext;
    //存放bean对象的列表
    private List<String> mList;
    //生成随机高度的Random
    private Random rand;
    //图片缓存容量的上限
    private int SizeofCache = 0;
    //LruCache实例
    private LruCache lruCache;
    //DiskLruCache的实例
    private DiskLruCache diskLruCache;
    public MyAdapter(Context mContext, List<String> mList) {
        this.mContext = mContext;
        this.mList = mList;
        rand = new Random();
        SizeofCache = (int) ((Runtime.getRuntime().maxMemory() / 1024) / 8);
        lruCache = new LruCache<String, Bitmap>(SizeofCache) {
            @Override
            protected int sizeOf(String key, Bitmap value) {
                return value.getByteCount() / 1024;
            }
        };
        File photo = getDiskCacheDir(mContext, "photo");
        if (!photo.exists()) {
            photo.mkdirs();
        }
        try {
            diskLruCache = DiskLruCache.open(photo, getAppVersion(mContext), 1, 10 * 1024 * 1024);
        } catch (IOException e) {
            e.printStackTrace();
        }
    }


    @NonNull
    @Override
    public MyAdapter.ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
        View view = LayoutInflater.from(mContext).inflate(R.layout.recyler_view, parent, false);
        ViewHolder holder = new ViewHolder(view);
        view.setOnClickListener(this);
        return holder;
    }


    @Override
    public void onBindViewHolder(@NonNull MyAdapter.ViewHolder holder, int position) {
        ViewGroup.LayoutParams layoutParams = holder.mIagme.getLayoutParams();
        layoutParams.height = rand.nextInt(100) + 200;
        holder.mIagme.setLayoutParams(layoutParams);
        //设置一个错误的图片
        //设置图片为不可见状态
        holder.mIagme.setImageResource(R.mipmap.ic_launcher);
        holder.mIagme.setVisibility(View.INVISIBLE);
        //防止错位
        holder.mIagme.setTag(mList.get(position));
        LoadImage loadImage = new LoadImage(holder);
        loadImage.execute(mList.get(position));
        holder.mIagme.setTag(mList.get(position));
        holder.itemView.setTag(position);
    }


    @Override
    public int getItemCount() {
        return mList.size();
    }






    public class ViewHolder extends RecyclerView.ViewHolder {
        private ImageView mIagme;


        public ViewHolder(View itemView) {
            super(itemView);
            mIagme = itemView.findViewById(R.id.image_view);
        }
    }


    *//**
 * 下载图片的异步任务类
 * <p>
 * 根据传入的uniqueName获取硬盘缓存的路径地址。
 * <p>
 * 获取当前应用程序的版本号。
 *
 * @param key    传入图片的key值,一般用图片url代替
 * @param bitmap 要缓存的图片对象
 * @param key 要取出的bitmap的key值
 * @return 返回取出的bitmap
 * <p>
 * 将URL进行MD5编码,防止特殊字符出现
 * @param key
 * @return 根据传入的uniqueName获取硬盘缓存的路径地址。
 * <p>
 * 获取当前应用程序的版本号。
 * @param key    传入图片的key值,一般用图片url代替
 * @param bitmap 要缓存的图片对象
 * @param key 要取出的bitmap的key值
 * @return 返回取出的bitmap
 * <p>
 * 将URL进行MD5编码,防止特殊字符出现
 * @param key
 * @return 根据传入的uniqueName获取硬盘缓存的路径地址。
 * <p>
 * 获取当前应用程序的版本号。
 * @param key    传入图片的key值,一般用图片url代替
 * @param bitmap 要缓存的图片对象
 * @param key 要取出的bitmap的key值
 * @return 返回取出的bitmap
 * <p>
 * 将URL进行MD5编码,防止特殊字符出现
 * @param key
 * @return 根据传入的uniqueName获取硬盘缓存的路径地址。
 * <p>
 * 获取当前应用程序的版本号。
 * @param key    传入图片的key值,一般用图片url代替
 * @param bitmap 要缓存的图片对象
 * @param key 要取出的bitmap的key值
 * @return 返回取出的bitmap
 * <p>
 * 将URL进行MD5编码,防止特殊字符出现
 * @param key
 * @return 根据传入的uniqueName获取硬盘缓存的路径地址。
 * <p>
 * 获取当前应用程序的版本号。
 * @param key    传入图片的key值,一般用图片url代替
 * @param bitmap 要缓存的图片对象
 * @param key 要取出的bitmap的key值
 * @return 返回取出的bitmap
 * <p>
 * 将URL进行MD5编码,防止特殊字符出现
 * @param key
 * @return 根据传入的uniqueName获取硬盘缓存的路径地址。
 * <p>
 * 获取当前应用程序的版本号。
 * @param key    传入图片的key值,一般用图片url代替
 * @param bitmap 要缓存的图片对象
 * @param key 要取出的bitmap的key值
 * @return 返回取出的bitmap
 * <p>
 * 将URL进行MD5编码,防止特殊字符出现
 * @param key
 * @return 根据传入的uniqueName获取硬盘缓存的路径地址。
 * <p>
 * 获取当前应用程序的版本号。
 * @param key    传入图片的key值,一般用图片url代替
 * @param bitmap 要缓存的图片对象
 * @param key 要取出的bitmap的key值
 * @return 返回取出的bitmap
 * <p>
 * 将URL进行MD5编码,防止特殊字符出现
 * @param key
 * @return 根据传入的uniqueName获取硬盘缓存的路径地址。
 * <p>
 * 获取当前应用程序的版本号。
 * @param key    传入图片的key值,一般用图片url代替
 * @param bitmap 要缓存的图片对象
 * @param key 要取出的bitmap的key值
 * @return 返回取出的bitmap
 * <p>
 * 将URL进行MD5编码,防止特殊字符出现
 * @param key
 * @return 根据传入的uniqueName获取硬盘缓存的路径地址。
 * <p>
 * 获取当前应用程序的版本号。
 * @param key    传入图片的key值,一般用图片url代替
 * @param bitmap 要缓存的图片对象
 * @param key 要取出的bitmap的key值
 * @return 返回取出的bitmap
 * <p>
 * 将URL进行MD5编码,防止特殊字符出现
 * @param key
 * @return 根据传入的uniqueName获取硬盘缓存的路径地址。
 * <p>
 * 获取当前应用程序的版本号。
 * @param key    传入图片的key值,一般用图片url代替
 * @param bitmap 要缓存的图片对象
 * @param key 要取出的bitmap的key值
 * @return 返回取出的bitmap
 * <p>
 * 将URL进行MD5编码,防止特殊字符出现
 * @param key
 * @return
 *//*
    class LoadImage extends AsyncTask<String, Integer, Bitmap> {
        Bitmap bitmap = null;
        InputStream is = null;
        String url = null;
        ViewHolder holder = null;


        DiskLruCache.Snapshot snapshot = null;
        FileInputStream fileInputStream = null;
        FileDescriptor fileDescriptor = null;
        BufferedInputStream in = null;
        BufferedOutputStream out = null;


        public LoadImage(ViewHolder holder) {
            this.holder = holder;
        }


        @Override
        protected Bitmap doInBackground(String... strings) {
            try {
                url = strings[0];
                Bitmap cachebitmap = getBitmapFromCache(url);
                //先从缓存中取,如果缓存不为空,则返回图片
                if (cachebitmap != null) {
                    Log.e(url, "存在于内存中,直接返回");
                    return cachebitmap;
                } else {


                    //如果内存缓存中取不到,再尝试从硬盘中取
                    Log.e(url, "内存中不存在,从硬盘缓存中找");
                    snapshot = diskLruCache.get(hashKeyForDisk(url));
                    //如果snapshot为空,则从网络下载图片
                    if (snapshot == null) {
                        Log.e(url, "硬盘中没有,从网络下载");
                        URL url_image = new URL(url);
                        HttpURLConnection conn = (HttpURLConnection) url_image.openConnection();
                        conn.setDoInput(true);
                        conn.connect();
                        //利用editor将图片写入硬盘缓存
                        is = conn.getInputStream();
                        in = new BufferedInputStream(is, 8 * 1024);
                        DiskLruCache.Editor editor = diskLruCache.edit(hashKeyForDisk(url));
                        OutputStream outputStream = editor.newOutputStream(0);
                        out = new BufferedOutputStream(outputStream, 8 * 1024);
                        int b;
                        while ((b = in.read()) != -1) {
                            out.write(b);
                        }
                        editor.commit();
                        diskLruCache.flush();
                        conn.disconnect();
                        out.close();
                        in.close();
                    }
                    //再次查找对应缓存
                    snapshot = diskLruCache.get(hashKeyForDisk(url));
                    //将bitmap写入内存缓存
                    fileInputStream = (FileInputStream) snapshot.getInputStream(0);
                    fileDescriptor = fileInputStream.getFD();
                    //如果fileDescriptor不为空,开始解析bitmap,加入到内存缓存中,并返回图片
                    if (fileDescriptor != null) {
                        Bitmap diskcachebitmap = BitmapFactory.decodeFileDescriptor(fileDescriptor);
                        if (diskcachebitmap == null) {
                            return null;
                        } else {
                            Log.e(url, "重新加入到内存缓存中");
                            addBitmapToCache(url, diskcachebitmap);
                            return diskcachebitmap;
                        }


                    }
                    return bitmap;


                }




            } catch (IOException e) {
                e.printStackTrace();
            }
            return null;
        }


        @Override
        protected void onPostExecute(Bitmap bitmap) {


            ImageView image = holder.mIagme;
            if (image.getTag().equals(url)) {
                image.setVisibility(View.VISIBLE);
                image.setImageBitmap(bitmap);
            }


            super.onPostExecute(bitmap);


        }
    }


    *//**
 * 根据传入的uniqueName获取硬盘缓存的路径地址。
 *//*
    public File getDiskCacheDir(Context context, String uniqueName) {
        String cachePath;
        if (Environment.MEDIA_MOUNTED.equals(Environment.getExternalStorageState()) || !Environment.isExternalStorageRemovable()) {
            cachePath = context.getExternalCacheDir().getPath();
        } else {
            cachePath = context.getCacheDir().getPath();
        }
        return new File(cachePath + File.separator + uniqueName);
    }


    *//**
 * 获取当前应用程序的版本号。
 *//*
    public int getAppVersion(Context context) {
        try {
            PackageInfo info = context.getPackageManager().getPackageInfo(context.getPackageName(), 0);
            return info.versionCode;
        } catch (PackageManager.NameNotFoundException e) {
            e.printStackTrace();
        }
        return 1;
    }


    *//**
 * @param key    传入图片的key值,一般用图片url代替
 * @param bitmap 要缓存的图片对象
 *//*
    public void addBitmapToCache(String key, Bitmap bitmap) {
        if (getBitmapFromCache(key) == null) {
            if (bitmap == null) {
                return;
            } else {
                lruCache.put(key, bitmap);
            }
        }


    }


    *//**
 * @param key 要取出的bitmap的key值
 * @return 返回取出的bitmap
 *//*
    public Bitmap getBitmapFromCache(String key) {


        return (Bitmap) lruCache.get(key);
    }


    *//**
 * 将URL进行MD5编码,防止特殊字符出现
 *
 * @param key
 * @return
 *//*
    public String hashKeyForDisk(String key) {
        String cacheKey;
        try {
            //信息摘要算法提供类
            final MessageDigest mDigest = MessageDigest.getInstance("MD5");
            mDigest.update(key.getBytes());
            cacheKey = bytesToHexString(mDigest.digest());
        } catch (NoSuchAlgorithmException e) {
            cacheKey = String.valueOf(key.hashCode());
        }
        return cacheKey;
    }


    private String bytesToHexString(byte[] bytes) {
        StringBuilder sb = new StringBuilder();
        for (int i = 0; i < bytes.length; i++) {
            //十六进制转换
            String hex = Integer.toHexString(0xFF & bytes[i]);
            if (hex.length() == 1) {
                sb.append('0');
            }
            sb.append(hex);
        }
        return sb.toString();
    }
    private onClickItem onClickItem;
    public interface onClickItem{
        void setOnClickItem(View view,int position);
    }
    @Override
    public void onClick(View v) {
        if (onClickItem != null){
            onClickItem.setOnClickItem(v,(int)v.getTag());
        }
    }
    public void setOnItemClickLister(onClickItem item){
        this.onClickItem = item;
    }*/

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值