最近小弟实现了, 一款相册, 但是在实现流水线的时候,recycleview 嵌套 recycleview 加载图片的时候,内存迟迟没法销毁。 导致占用内存到 2g. 下面贴一贴我的代码
public class PhotoAdapter extends RecyclerView.Adapter<PhotoAdapter.ViewHolder> {
private Context context;
private List<PhotoGroup> photoGroupList;
// 构造方法(将图片数据传入)
public PhotoAdapter(List<PhotoGroup> photoGroupList) {
this.photoGroupList = photoGroupList;
}
@Override
public int getItemViewType(int position) {
if (position == 0) {
return 0;
}
return -1;
}
@NonNull
@Override
public ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
if (context == null) {
context = parent.getContext();
}
// 返回外层 分组的 item
View view = LayoutInflater.from(context).inflate(R.layout.image_group_item, parent, false);
final ViewHolder holder = new ViewHolder(view);
return holder;
}
@Override
public void onViewRecycled(@NonNull ViewHolder holder) {
super.onViewRecycled(holder);
Glide.with(holder.itemView).clear(holder.itemView);
Glide.with(holder.itemView).clear(holder.cardView);
Glide.with(holder.itemView).clear(holder.recyclerView);
}
//将数据绑定到控件上
@Override
public void onBindViewHolder(@NonNull ViewHolder holder, int position) {
PhotoGroup PhotoGroup = photoGroupList.get(position);
ChildAdapter childAdapter = (ChildAdapter) holder.recyclerView.getAdapter();
if (childAdapter == null) {
// 设定 image_group_item 布局(每列显示 4 个子布局 image_child_item )
GridLayoutManager manager = new GridLayoutManager(context, 4);
holder.recyclerView.setItemViewCacheSize(2000);
holder.recyclerView.setHasFixedSize(true);
holder.recyclerView.setNestedScrollingEnabled(false);
holder.recyclerView.setLayoutManager(manager);
// 设置子布局的适配器 [ PhotoGroup.getPhotoArrayList() 是一个分组中的图片数据]
holder.recyclerView.setAdapter(new ChildAdapter(PhotoGroup.getPhotoArrayList()));
} else {
// 重用子布局的适配,如果已经初始化过,直接调用 notifyDataSetChanged() 刷新布局就行
childAdapter.setData(PhotoGroup.getPhotoArrayList());
// childAdapter.notifyDataSetChanged();
}
}
@Override
public int getItemCount() {
return photoGroupList.size();
}
// ViewHolder 对应 image_group_item 文件,里面元素只有最外层 CardView 和一个嵌套 RecyclerView
static class ViewHolder extends RecyclerView.ViewHolder {
RelativeLayout cardView;
RecyclerView recyclerView;
public ViewHolder(View view) {
super(view);
cardView = (RelativeLayout) view;
recyclerView = (RecyclerView) view.findViewById(R.id.tupian_item_recyclerView);
recyclerView.addOnScrollListener(new ImageAutoLoadScrollListener(view.getContext()));
}
}
/*****************************ChildAdapter ***************************************/
// 嵌套子适配(内部类)
public class ChildAdapter extends RecyclerView.Adapter<ChildViewHolder> {
// 每一个组的图片数据
private ArrayList<Photo> photoList;
//构造函数
public ChildAdapter(ArrayList<Photo> photoList) {
this.photoList = photoList;
}
//用于更新图片数据
public void setData(ArrayList<Photo> photoList) {
this.photoList = photoList;
}
@NonNull
@Override
public ChildViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
if (context == null) {
context = parent.getContext();
}
View view = LayoutInflater.from(context).inflate(R.layout.image_child_item, parent, false);
final ChildViewHolder holder = new ChildViewHolder(view);
return holder;
}
@Override
public void onViewRecycled(@NonNull ChildViewHolder holder) {
super.onViewRecycled(holder);
Glide.with(holder.itemView.getContext()).clear(holder.imageView);
}
@Override
public void onBindViewHolder(@NonNull ChildViewHolder holder, int position) {
Photo image = photoList.get(position);
Uri uri = ContentUris.withAppendedId(
UriUtil.INSTANCE.getMediaType(image.getMediaType()),
image.getId()
);
Glide.with(holder.imageView.getContext())
.asDrawable()
.load(uri)
.thumbnail(0.1f)
.override(SizeUtils.dp2px(100), SizeUtils.dp2px(100))
.placeholder(R.drawable.folder_ripple)
.format(DecodeFormat.PREFER_RGB_565)
.skipMemoryCache(true)
.into(holder.imageView);
}
@Override
public int getItemCount() {
return photoList.size();
}
}
}
下面是我流水线布局的代码
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent">
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/main_recyclerView"
android:layout_width="match_parent"
android:layout_height="match_parent"/>
</androidx.constraintlayout.widget.ConstraintLayout>
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:id="@+id/image_child_item_id"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_margin="2dp"
app:cardCornerRadius="4dp">
<com.example.pic.picmanager.MyRoundImageView
android:id="@+id/image_item_imageView"
android:layout_width="match_parent"
android:layout_height="100dp"
android:adjustViewBounds="true"
android:scaleType="centerCrop"
app:round="4dp" />
</RelativeLayout>
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:id="@+id/image_group_item_id"
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:cardCornerRadius="4dp"
app:cardElevation="0dp">
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/tupian_item_recyclerView"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
</RelativeLayout>
1
jeesk OP 这种嵌套布局导致 glide 加载图片无法释放内存。 难受中
|
2
hahabird 2022-08-21 10:54:53 +08:00
holder.recyclerView.setItemViewCacheSize(2000);这句是设置缓存数量的吗?
用 profile 看下内存占用? |
4
janus77 2022-08-21 12:39:46 +08:00
嵌套本身就是复用会差点的……
我看你对 child adapter 判断了为空,你可以打印日志,然后多滚动一下列表看看是否命中了不为空的条件。如果大多数都是走的为空,那说明你的 child adapter 一直是在 new 的,这样会影响内存 你可以用对象池,把 child adapter 也做缓存,另外在 child adapter 里面的 glide 内存回收管理这块代码注意下 |
5
hyyou2010 2022-08-21 12:47:42 +08:00
从另一个角度建议
1 、从产品角度做简化,不要复杂的嵌套 2 、试试用 compose 写界面,方便太多了,没有 adapter 这些 |
7
devfeng 2022-08-21 16:50:36 +08:00
没懂,你这个场景不是直接用一个 RecyclerView+GridLayoutManager 就可以了吗,设置好 SpanSizeLookup
|
8
seelight 2022-08-21 16:54:22 +08:00
可以试一下 Compose, 无限嵌套, 没有性能影响, 还不用写 adapter.
|