[英]Android - Custom dynamically-generated compound View recreated in RecyclerView, causing poor performance
我使用的是自定義的CompoundView
延伸LinearLayout
的顯示項目RecyclerView
。 每個項目都會顯示一個包含多個段落和圖像的文章。
CompoundView
基於CompoundView.setData(List<DataPiece> pieces)
附加的數據動態添加TextView
或ImageView
,其數目在附加數據之前是未知的。
每個DataPiece
對象都告訴CompoundView
它是文本還是圖像。 這是CompoundView.setData(List<DataPiece> pieces)
的代碼:
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;
}
}
}
在RecyclerView.Adapter.onBindViewHolder()
,通過調用MyViewHolder.compoundView.setData(...)
將數據附加到CompoundView
。 創建RecyclerView
時,它工作正常。
但是,對於具有多個ImageView
和TextView
的CompoundView
項,當我滾動離開它然后向后滾動時,滾動會變得非常不平滑。
我想這是因為removeAllViews()
在setData()
被調用,並CompoundView
for循環建立由回收再執行。 但是我不知道如何避免這種情況。
而且我也想知道為什么在RecyclerView
使用TextView
(帶有Images)時,即使它也被回收了,所以滾動總是總是平滑的。
提前致謝!
確定最佳方法可能有多種考慮。
首先,您對回收商列表中的最大物品數量有什么想法嗎? 如果只是少數幾個,也許您可以CompundView
RecyclerView
方法,只需將CompundView
添加到ScrollView
托管的容器中。
其次-每個項目的布局是否相當復雜(又有很多TextViews
, ImageViews
等)? 如果是的話,也許您可以采用類似於ExpandableListView
-在每個列表項中顯示一個摘要,並在單擊時擴展到該項的完整布局。
第三,如果以上都不是可接受的,並且您仍然想采用當前的方法,請不要在綁定方法中構造/添加視圖。 當系統要求您構造視圖時,請在onCreateViewHolder
執行此操作(我不確定,但是到onBindViewHolder
調用時,您的視圖可能已經添加到層次結構中,並且對它的任何層次結構更改都已經對其容器產生連鎖反應-但請不要相信我,我實際上不知道該視圖已經添加,這只是一個假設)。 您將必須為每個項目分配不同的類型,以便在onCreateViewHolder
可以將視圖類型與支持數據進行匹配(用於添加相應數量的子視圖); 每次都從頭開始創建視圖-這樣,您無需調用removeAllViews
。 像這樣(我省略了與案例無關的適配器部分):
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);
}
}
}
RecyclerView
應該重用視圖。 如果您丟棄已經創建的TextView
/ ImageView
對象並每次都創建一個新對象,它將很慢。
聽起來您需要具有多種視圖類型的RecyclerView
。 這個想法是創建多個視圖持有者-其中一些使用ImageView
,其他使用TextView
。 您將必須重寫適配器的getItemViewType(int position)方法-它應該為IMAGE項目和TEXT項目返回不同的值。 onCreateViewHolder(ViewGroup parent,int viewType)接收一個viewType參數,因此您知道要在其中創建哪種ViewHolder。 在onBindViewHolder(VH持有人,int位置)中,您可以假定傳遞給您的持有人是正確的類型(即,對於TEXT項使用TextView
的類型,對於IMAGE項使用ImageView
的類型),因此無需刪除其子視圖,然后再次創建它們。
有一個關於RecyclerView的適配器好的文章與多個視圖類型在這里 。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.