簡體   English   中英

Android-在RecyclerView中重新創建自定義動態生成的復合視圖,導致性能不佳

[英]Android - Custom dynamically-generated compound View recreated in RecyclerView, causing poor performance

我使用的是自定義的CompoundView延伸LinearLayout的顯示項目RecyclerView 每個項目都會顯示一個包含多個段落和圖像的文章。

CompoundView基於CompoundView.setData(List<DataPiece> pieces)附加的數據動態添加TextViewImageView ,其數目在附加數據之前是未知的。

每個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時,它工作正常。

但是,對於具有多個ImageViewTextViewCompoundView項,當我滾動離開它然后向后滾動時,滾動會變得非常不平滑。

我想這是因為removeAllViews()setData()被調用,並CompoundView for循環建立由回收再執行。 但是我不知道如何避免這種情況。

而且我也想知道為什么在RecyclerView使用TextView (帶有Images)時,即使它也被回收了,所以滾動總是總是平滑的。

提前致謝!

確定最佳方法可能有多種考慮。

首先,您對回收商列表中的最大物品數量有什么想法嗎? 如果只是少數幾個,也許您可​​以CompundView RecyclerView方法,只需將CompundView添加到ScrollView托管的容器中。

其次-每個項目的布局是否相當復雜(又有很多TextViewsImageViews等)? 如果是的話,也許您可​​以采用類似於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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM