RecyclerView viewholder 中的动态项目
Dynamic items in viewholder on RecyclerView
如果我们有 N 个类别(根据 REST API,在 1 到 100 之间)并且每个类别都有 X 个项目(在 1 到 50 之间,具体取决于类别),最好的方法是什么类别 RecyclerView?
要添加此操作,我在方法 "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()
数字 1 是通过使用 convertView
参数解决的,数字 2 是通过称为 "view holder pattern" 的东西解决的。当 Google 开发团队创建 RecyclerView
API 来替换 ListView
时,他们让 "view holders" 成为 first-class 公民,现在每个人都使用 RecyclerView.ViewHolder
s 默认。
请务必记住,避免重复查看 inflation 和重复查看查找所带来的性能提升 非常有价值 以至于 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);
}
}
你的绑定方法中的这个 for
循环与我上面的天真 getView()
实现有所有相同的问题。为类别中的每个项目创建一个新视图,并调用 findViewById()
来获取它的 ImageView
会很昂贵,尤其是当用户抛出列表时。
要解决性能问题,只需对 "inner" 内容列表应用与 "outer" 内容相同的逻辑:对项目使用 RecyclerView
(在每个ViewHolder
类别)。
这是一个非常简单的示例应用程序,它说明了我的解决方案:https://gist.github.com/zizibaloob/2eb64f63ba8d1468100a69997d525a54
如果我们有 N 个类别(根据 REST API,在 1 到 100 之间)并且每个类别都有 X 个项目(在 1 到 50 之间,具体取决于类别),最好的方法是什么类别 RecyclerView?
要添加此操作,我在方法 "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()
数字 1 是通过使用 convertView
参数解决的,数字 2 是通过称为 "view holder pattern" 的东西解决的。当 Google 开发团队创建 RecyclerView
API 来替换 ListView
时,他们让 "view holders" 成为 first-class 公民,现在每个人都使用 RecyclerView.ViewHolder
s 默认。
请务必记住,避免重复查看 inflation 和重复查看查找所带来的性能提升 非常有价值 以至于 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); } }
你的绑定方法中的这个 for
循环与我上面的天真 getView()
实现有所有相同的问题。为类别中的每个项目创建一个新视图,并调用 findViewById()
来获取它的 ImageView
会很昂贵,尤其是当用户抛出列表时。
要解决性能问题,只需对 "inner" 内容列表应用与 "outer" 内容相同的逻辑:对项目使用 RecyclerView
(在每个ViewHolder
类别)。
这是一个非常简单的示例应用程序,它说明了我的解决方案:https://gist.github.com/zizibaloob/2eb64f63ba8d1468100a69997d525a54