连网图片的处理:
- 在onBindViewHolder方法中获取本行对应的图片网址,根据图片网址下载图片
关于下载图片的缓存处理:
方式一: 纯手动处理
- 缓存处理的大体思路:
将下载好的图片分别存储在两个位置:
- 运行内存中
特点:页面退出时,清空
2. 本地
特点:只要不手动删除或者程序卸载,一致存在
每当要显示图片的时候,先去内存中读取图片,如果有图片,直接显示,如果没有图片,再到本地进行读取,如果没有下载。并且在下载后将图片分别存入内存和本地
图片的3级缓存
1.LruCache- 特点:
- 默认支持存储键值对
- 在初始化LruCache对象指定做多存储多少图片
- 一旦达到最大存储上限时,会自动删除最先存储的图片,再将新图片添加到LruCache中
2.SoftReferences 软引用
- 本身不支持存储n组键值对,每一个SoftReferences对象只能存储一张图片
- 如果要通过存储多张图片,需要借助HashMap<String,SoftRerences>
- 自动根据当前的内存情况存储图片,如果内存充足,那么一直存储图片
- 如果内存不够用,会自动将存储的图片删除掉
3级缓存的实现步骤:
图片的读取:
先读LruCache,没有读SoftReferences,再没有,读本地,再没有,连网
图片的存储:
连网下载后将图片存入LruCache和本地
当LruCache中的图片被自动删除的时候,将删除的图片添加到SoftReferences中进行存储
class MyFirstAdapter extends RecyclerView.Adapter<MyFirstAdapter.MyViewHolder> {
//LruCache对象
LruCache<String, Bitmap> cache;
//创建HashMap对象,用于存储多张存入软引用的图片
HashMap<String, SoftReference<Bitmap>> map = new HashMap<>();
//在构造方法中初始化LruCache对象
public MyFirstAdapter() {
//获取当前可用的运行内存的1/8
int maxSize = (int) (Runtime.getRuntime().maxMemory() / 8);
//通过构造方法的参数指定当前LruCache中最多存储多少图片
cache = new LruCache<String, Bitmap>(maxSize) {
/*
* 通过返回值获取当前要加到LruCache中的图片的大小
* */
@Override
protected int sizeOf(String key, Bitmap value) {
return value.getByteCount();
}
/*
* 当LruCache中的图片被删除时运行此方法
* evicted: 图片是否是被系统自动删除的
* */
@Override
protected void entryRemoved(boolean evicted, String key, Bitmap oldValue, Bitmap newValue) {
super.entryRemoved(evicted, key, oldValue, newValue);
if (evicted) {
//图片被系统自动删除,可以在此处将删除的图片添加到SoftReferences中存储
map.put(key,new SoftReference<Bitmap>(oldValue));
}
}
};
}
//自定义方法,用于从缓存中取出图片
public Bitmap getCacheBitmap(String url) {
//1. 从LruCache中取图片
Bitmap result = cache.get(url);
if (result == null) {
//2. 从SoftReferences中读取图片
SoftReference<Bitmap> soft = map.get(url);
if (soft != null) {
result = soft.get(); //从软引用中取出图片
if (result == null) {
//3. 从本地读取图片
return result = BitmapFactory.decodeFile("data/data/" + getPackageName() + "/cache/" + url);
}
}
}
return result;
}
@Override
public MyViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
Log.i("====", "====== onCreateViewholder");
return new MyViewHolder(LayoutInflater.from(MainActivity.this)
.inflate(R.layout.item, parent, false));
}
@Override
public void onBindViewHolder(final MyViewHolder holder, final int position) {
Log.i("====", "====== onBindViewHolder " + position);
holder.tv.setText(list.get(position).getPicCategoryName());
//设置imageview上显示的默认图片
holder.iv.setImageResource(R.mipmap.ic_launcher);
//获取当前要显示的图片对应的图片网址
String url = list.get(position).getCategoryPic();
//从缓存中取出图片
Bitmap bitmap = getCacheBitmap(url);
if (bitmap != null) {
//缓存中有图片
holder.iv.setImageBitmap(bitmap);
} else {
//缓存中没有图片,连网进行下载
new MyImgTask(new MyImgTask.DoImgBackListener() {
@Override
public void onBack(Bitmap t,String url) {
holder.iv.setImageBitmap(t);
// 将图片存入LruCache中
cache.put(url,t);
//将图片存入本地
//getPackageName()用于获取当前程序的程序包名
File file = new File("data/data/" + getPackageName() + "/cache");
if (!file.exists()) {
file.mkdirs(); //如果文件夹不存在,创建文件夹
}
try {
FileOutputStream fos = new FileOutputStream("data/data/" + getPackageName() + "/cache/"+url);
//将图片数据存入指定路径中
t.compress(Bitmap.CompressFormat.PNG,100,fos);
} catch (FileNotFoundException e) {
e.printStackTrace();
}
}
}).execute(url);
}
}
//通过返回值控制列表中总共要显示多少个条目
@Override
public int getItemCount() {
return list.size();
}
/*
* 创建一个ViewHolder的子类
* 用于初始化item中控件对象
* */
class MyViewHolder extends RecyclerView.ViewHolder {
public TextView tv;
public ImageView iv;
//参数:列表中显示的item中的View对象
public MyViewHolder(View itemView) {
super(itemView);
tv = (TextView) itemView.findViewById(R.id.textView);
iv = (ImageView) itemView.findViewById(R.id.imageView);
}
}
}