我正在尝试重新创建这个:
我有一个数据列表:
List<Block> blocks;
Block.java
类有一个方法 getNumBlocks()
,它返回该项目应显示的 block 数。 block 的数量可以小到 1 个 block ,大到 20 个 block 。
我创建了一个普通的 RecyclerView 适配器,以及该 block 的 ImageView
布局:
public class BlockAdapter extends RecyclerView.Adapter<BlockAdapter.ViewHolder> {
private Context context;
private List<Block> blocks;
public BlockAdapter(Context context, List<Block> blocks) {
this.context = context;
this.blocks = blocks;
}
public class ViewHolder extends RecyclerView.ViewHolder {
public ImageView block;
public ViewHolder(View v) {
super(v);
block = (ImageView) v.findViewById(R.id.block);
}
}
@Override
public BlockAdapter.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
LayoutInflater inflater = LayoutInflater.from(context);
View view = inflater.inflate(R.layout.block_layout, parent, false);
return new ViewHolder(view);
}
@Override
public void onBindViewHolder(final ViewHolder holder, int position) {
Block block = blocks.get(position);
// How to use block.getNumBlocks() to show the correct number of blocks?
}
@Override
public int getItemCount() {
return blocks.size();
}
}
这里是block_layout.xml
(它只是一个空的LinearLayout, block 应该添加到这个LinearLayout内部):
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="@drawable/card_bg"
android:padding="16dp">
</LinearLayout>
这是 block.xml
布局:
<ImageView
android:id="@+id/block"
android:layout_width="18dp"
android:layout_height="18dp"
android:layout_marginEnd="8dp"
android:layout_marginRight="8dp" />
所以我的问题是,如何实现它,以便它显示每个 RecyclerView 项目的正确 block 数?
实现性能明智的最佳方法是什么?
最佳答案
您关心性能是件好事。每次想要显示一行时创建新的 ImageViews 违背了回收 View 的想法。基本上,当滚动时,您只会重复使用顶层 View ,但每次出现在屏幕上时仍会为任何项目创建新的 ImageViews
。
为了解决这个问题,您可以创建自己的 View 池,如下所示:
public class BlockAdapter extends RecyclerView.Adapter<BlockAdapter.ViewHolder> {
private final List<Block> blocks;
private final List<ImageView> imageViewPool = new LinkedList<>();
public BlockAdapter(List<Block> blocks) {
this.blocks = blocks;
}
@Override
public int getItemCount() {
return blocks.size();
}
@Override
public BlockAdapter.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
return new ViewHolder(LayoutInflater.from(parent.getContext()).inflate(R.layout.block_layout, parent, false));
}
@Override
public void onBindViewHolder(final ViewHolder holder, int position) {
holder.bind(blocks.get(position));
}
public class ViewHolder extends RecyclerView.ViewHolder {
private final List<ImageView> imageViews = new ArrayList<>();
private final ViewGroup container;
public ViewHolder(View v) {
super(v);
container = (ViewGroup) itemView;
}
public void bind(Block block) {
recycleImageViews();
for (int i = 0; i < block.getNumBlocks(); ++i) {
final ImageView imageView = getRecycledImageViewOrCreate();
imageViews.add(imageView);
container.addView(imageView);
}
}
private ImageView getRecycledImageViewOrCreate() {
if (imageViewPool.isEmpty()) {
return (ImageView)LayoutInflater.from(container.getContext()).inflate(R.layout.block, container, false);
}
return imageViewPool.remove(0);
}
public void recycleImageViews() {
imageViewPool.addAll(imageViews);
imageViews.clear();
container.removeAllViews();
}
}
@Override
public void onViewRecycled(ViewHolder holder) {
super.onViewRecycled(holder);
holder.recycleImageViews();
}
}
此解决方案背后的想法与 RecyclerView
的做法非常相似。
每次ViewHolder
想要呈现子项目时,它都会:
- 从
imageViewPool
中获取ImageView。如果池子里没有备用的,就会充气一个新的。 - 将此
ImageView
附加到其自身。
稍后,当特定的 ViewHolder
被重新使用或回收时,它将:
- 将所有
ImageViews
与其自身分离。 - 将这些
ImageViews
返回到可重用池,以便屏幕上出现的下一个项目可以使用它们。
关于android - 在 RecyclerView 项目中显示动态数量的 View ?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/43101231/