需要导入一个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;
}*/