如果我们有N个类别(根据REST API在1至100之间),并且每个类别都有X个项目(在1至50之间,取决于类别),那么制作RecyclerView类别的最佳方法是什么?

android - RecyclerView上的Viewholder中的动态项目-LMLPHP

为此,我在“ onBindViewHolder”方法中为类别的每个项目添加卡片视图,如下所示:

    @Override
public void onBindViewHolder(MoviesViewHolder holder, int i) {
    holder.title.setText(items.get(i).getTitle());

     // I add a CardView (item_category.xml) for each item in the list

    for (ObjectShort object: items.get(i).getObjects()) {
        LayoutInflater inflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
        View view = inflater.inflate(R.layout.item_category, holder.linearCategories, false);
        ImageView img = (ImageView) view.findViewById(R.id.iv_wallpaper);
        imageLoader.load(img, object.getImg().getPoster().getThumbnail());
        holder.linearCategories.addView(view);
    }

}


并且当它被回收时,我删除了“ onViewRecycled”中的ITEMS元素,因为如果在垂直滚动和重新加载类别时不这样做,则会再次添加重复项:

    @Override
public void onViewRecycled(MoviesViewHolder holder) {
    // delete all items
    holder.linearCategories.removeAllViews();
}


有什么更好的方法吗?这无效并且滚动非常慢

谢谢大家

最佳答案

为了回答您的问题,我将回到ListView的过去。想象一下,我有一个简单的列表,其中每行只是一个标题和一个图像。 getView()一个真正幼稚的实现以支持该列表可能如下所示:

@Override
public View getView(int position, View convertView, ViewGroup parent) {
    LayoutInflater inflater = LayoutInflater.from(parent.getContext());
    View view = inflater.inflate(R.layout.itemview, parent, false);

    TextView title = view.findViewById(R.id.title);
    title.setText("hello world");

    ImageView image = view.findViewById(R.id.image);
    image.setImageResource(R.drawable.my_image);

    return view;
}


此实现有两个主要的性能问题来源:


我们每次都在夸大新观点
我们每次都打findViewById()


通过使用convertView参数解决了数字1,并通过称为“视图持有者模式”的东西解决了数字2。当Google开发人员团队创建RecyclerView API替换ListView时,他们将“视图持有者”定为一流公民,现在每个人都默认使用RecyclerView.ViewHolder

重要的是要记住,避免重复视图膨胀和重复视图查找所带来的性能提升非常宝贵,以至于Google将它们引入了新系统中。

现在让我们看一下您的代码...


public void onBindViewHolder(MoviesViewHolder holder, int i) {
    ...
    for (ObjectShort object: items.get(i).getObjects()) {
        LayoutInflater inflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
        View view = inflater.inflate(R.layout.item_category, holder.linearCategories, false);
        ImageView img = (ImageView) view.findViewById(R.id.iv_wallpaper);
        imageLoader.load(img, object.getImg().getPoster().getThumbnail());
        holder.linearCategories.addView(view);
    }
}



您的bind方法中的这个for循环具有与我上面的朴素getView()实现相同的所有问题。为类别中的每个项目扩展一个新视图,并调用findViewById()来获取其ImageView将会非常昂贵,尤其是当用户浏览该列表时。

若要解决性能问题,只需对“内部”内容列表应用与对“外部”内容相同的逻辑:对项目使用RecyclerView(对于类别,在每个ViewHolder内部)。

这是一个非常简单的示例应用程序,用于说明我的解决方案:https://gist.github.com/zizibaloob/2eb64f63ba8d1468100a69997d525a54

关于android - RecyclerView上的Viewholder中的动态项目,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/47255744/

10-12 05:17