Android-在RecyclerView中重新创建自定义动态生成的复合视图,导致性能低下
我正在使用一个自定义的Android-在RecyclerView中重新创建自定义动态生成的复合视图,导致性能低下,android,performance,android-layout,android-view,android-recyclerview,Android,Performance,Android Layout,Android View,Android Recyclerview,我正在使用一个自定义的CompoundView,它扩展了LinearLayout来显示RecyclerView的项目。每个项目显示一篇包含多个段落和图像的文章 CompoundView根据CompoundView.setData(列表项)附加的数据动态添加TextView或ImageView,在附加数据之前,其数量未知 每个DataPiece对象告诉CompoundView它是文本还是图像。下面是CompoundView.setData(列表项): public void setData(列表项
CompoundView
,它扩展了LinearLayout
来显示RecyclerView
的项目。每个项目显示一篇包含多个段落和图像的文章 CompoundView
根据CompoundView.setData(列表项)
附加的数据动态添加TextView
或ImageView
,在附加数据之前,其数量未知 每个DataPiece
对象告诉CompoundView
它是文本还是图像。下面是CompoundView.setData(列表项)
:
public void setData(列表项){
移除所有视图();
用于(数据件数据件:件){
开关(dataPiece.getType()){
案例图像:
ImageView=newImageView(getContext());
...
addView(imageView);
打破
案例文本:
TextView TextView=newtextView(getContext());
...
addView(textView);
打破
}
}
}
在RecyclerView.Adapter.onBindViewHolder()
中,通过调用MyViewHolder.CompoundView.setData(…)
将数据附加到CompoundView
。当创建RecyclerView
时,它可以正常工作
但是,对于具有多个ImageView
s和TextView
s的CompoundView
项目,当我滚动离开它然后向后滚动时,滚动会变得非常不平滑
我猜这是因为setData()
中的removeallview()
被调用,循环器再次执行CompoundView
创建循环。但我不知道如何避免这种情况。
我还想知道为什么在RecyclerView
中使用TextView
(带图像)时,即使它也是循环使用的,滚动也总是平滑的。
提前谢谢
RecyclerView
应该重用视图。如果您扔掉已经创建的TextView
/ImageView
对象,每次都创建新的对象,则速度会很慢
听起来您需要一个具有多种视图类型的RecyclerView
。我们的想法是创建多个视图持有者,其中一些具有ImageView
,另一些具有TextView
。您必须重写适配器的方法-它应该为图像项和文本项返回不同的值。将接收viewType参数,以便您知道要在其中创建哪种类型的ViewHolder。在中,您可以假设传递给您的保持架是正确的类型(即,对于文本项目,具有TextView
的类型,对于图像项目,具有ImageView
的类型),因此无需删除其子视图并再次创建它们
有一篇很好的文章介绍了RecyclerView的多视图适配器。在决定最佳方法时,可能需要考虑多种因素 首先,你对回收商名单上的最大物品数量有什么想法?如果只是一小部分,也许您可以放弃
RecyclerView
方法,将CompundView
添加到由ScrollView
托管的容器中
第二,每个项目的布局是否相当复杂(也就是说,其中是否有许多文本视图
,图像视图
等)?如果是,也许您可以采取类似于ExpandableListView
的方法—将摘要显示为每个列表项,并在单击时展开到该项的完整布局
第三,如果以上任何一个都不可接受,并且您仍然希望采用当前的方法,那么不要在binding方法中构造/添加您的视图。当系统希望您构建视图时,请在onCreateViewHolder
中执行此操作(我不确定,但当你在onBindViewHolder
上被调用时,你的视图可能已经被添加到层次结构中,对它的任何层次结构的更改都会对其容器产生连锁反应-但不要相信我的话,我实际上不知道视图已经被添加,这只是一个假设)。您必须为每个项目分配不同的类型,以便在onCreateViewHolder
中,您可以将视图类型与支持数据相匹配(用于添加相应数量的子视图);每次都从头开始创建视图-这样您就不需要调用removeallview
(我遗漏了适配器中与壳体无关的部分):
公共类RecycleServiceAdapter扩展了RecyclerView.Adapter{
柱叶螨;
公共回收服务适配器(ArrayList项){
mItems=项目;
}
@凌驾
public RecyclerView.ViewHolder onCreateViewHolder(视图组父级,int-viewType){
CompoundView CompoundView=新的CompoundView();
List dataPieces=mItems.get(viewType);
对于(int i=0;i compoundView.getChildAt(j)如果您仅为要创建的RecyclerView
列表使用自定义/复合视图
,那么最好为一个列表项创建一个XML布局,然后使用RecyclerView
的内置方法将数据添加到列表项中的视图
中。@Farbod
public void setData(List<DataPiece> pieces) {
removeAllViews();
for (DataPiece dataPiece : pieces) {
switch (dataPiece.getType()) {
case IMAGE:
ImageView imageView = new ImageView(getContext());
...
addView(imageView);
break;
case TEXT:
TextView textView = new TextView(getContext());
...
addView(textView);
break;
}
}
}
public class RecyclerViewAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> {
ArrayList<DataPiecesList> mItems;
public RecyclerViewAdapter(ArrayList<DataPiecesList> items) {
mItems = items;
}
@Override
public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
CompoundView compoundView = new CompoundView();
List<DataPiece> dataPieces = mItems.get(viewType);
for (int i = 0; i < dataPieces.size(); i++)
{
// construct TextView or ImageView or whatever
compoundView.add(child);
}
MyViewHolder view = new MyViewHolder(compoundView);
return view;
}
@Override
public void onBindViewHolder(RecyclerView.ViewHolder viewHolder, int i) {
CompoundView compoundView = viewHolder.itemView;
DataPiece dataPiece = mItems.get(i);
for (int j = 0; j < compoundView.getChildCount(); j++)
{
compoundView.getChildAt(j) <- dataPiece.get(j);
}
}
@Override
public int getItemViewType(int position) {
return position;
}
@Override
public int getItemCount() {
return mItems.size();
}
public class MyViewHolder extends RecyclerView.ViewHolder {
...
public MyViewHolder(View itemView) {
super(itemView);
}
}
}