web-dev-qa-db-ja.com

RecyclerViewで一部のアイテムをリサイクルしないようにしたい

私はRecyclerViewを使用していますが、内部には異種のビューがあります このチュートリアルで見られるように

私は、RecyclerViewsの中に、RecyclerViewsでもあるアイテムをいくつか持っています。想像するのは難しいですか? Playストアのレイアウトをコピーするとしましょう。1つの大きなRecyclerViewで、垂直方向の線形レイアウトを持ち、多くの要素で満たされています:単一のアプリとアプリのカルーセル。

追加するアイテムが単一のアプリのレイアウトである場合、ID 1が使用され、単一のアイテムのレイアウトを追加します。それ以外の場合、カルーセルを追加する必要がある場合は、1つの要素をメインのRecyclerViewに追加します。独自のアダプターを持つ別のRecyclerViewです。

それは非常にうまくいきます。メインのRecyclerViewをスクロールする場合を除きます。どうして?一部のビューは表示されなくなったときに破棄され、onBindViewHolder()メソッドで再作成されるためです。なぜここに?メインのRecyclerViewのAdapterが位置Xを渡してからOnBindViewHolder()を呼び出すためです。後者は、独自のアダプターを使用して新しいRecyclerViewを作成し、それに割り当てます。毎回再膨張させるのが重いという理由だけで、これらの見解を維持したいと思います。

これは可能ですか?もしそうなら、どのように教えてもらえますか?

27
Joaquin Iurchuk

これを使って:

_recyclerView.getRecycledViewPool().setMaxRecycledViews(TYPE_CAROUSEL, 0);
_

これにより、viewType _TYPE_CAROUSEL_のビューはリサイクルされませんが、このタイプのアイテム数が非常に多い場合、パフォーマンスが大幅に低下し、OOMEが発生する可能性があります

[〜#〜] edit [〜#〜]

MML13の答えを読んだ後、私はそれがあなたのために働くかもしれないと思う。ビューが外側のRecyclerViewで再バインドされると、カルーセルのアイテムが再膨張するのが心配です。それらのすべてのカルーセルが同じタイプである場合、つまり、すべて同じアダプターを使用する場合、アダプターを外側のRecyclerViewのViewHolder内に保持し、データを交換してnotifyDataSetChanged()またはnotifyItemRangeChanged(...) onを呼び出すことができます。再バインドされたときのこのアダプター。これにより、すべてのカルーセルビューとそれらのカルーセル内のすべてのビューがリサイクルされます。

63
Sourabh

アダプタのonBindViewholder()メソッドで以下のコードを設定することもできます。

holder.setIsRecyclable(false);

このリンクから参照しました

http://aphoe.com/blog/prevent-androids-recyclerview-recycling-views/

23
N-Y

一部のビューは表示されなくなると破棄され、onBindViewHolder()メソッドで再作成されるためです。

それは真実ではなく、それらは再び作成されず、単に再バインドされます。位置X(スクラップまたはリサイクラ内)のビューがある場合、RecyclerViewはそれを使用して再バインドします。

毎回再膨張させるのが重いという理由だけで、それらの見解を維持したいと思います。

メインのRecyclerViewがそれらを保持します。 2番目のRecyclerViewのアダプターデータを変更し、notifyDataSetChangedを呼び出すだけです。メインRecyclerViewviewHolder内に2番目のRecyclerViewアダプターも格納します。

9
user5703518

アダプタに追加できます:

_@Override
public void onBindViewHolder(final CommentViewHolder viewHolder, final int position) {
    viewHolder.setIsRecyclable(false);
}
_

このアイテムをリサイクルできるかどうかをリサイクル業者に通知します。 setIsRecyclable()が後でtrueに設定されるまで、リサイクルできないビューは他のアイテムに再利用されません。 setIsRecyclable()への呼び出しは常にペアにする必要があります(setIsRecyclabe(false)への1回の呼び出しは、その後のsetIsRecyclable(true)への呼び出しと常に一致させる必要があります)。状態は内部的に参照カウントされるため、呼び出しのペアはネストできます。

5

アクティビティに次の行を設定します

recyclerView.getRecycledViewPool().setMaxRecycledViews(1,0);

recyclerViewAdapterクラスで以下のコードを設定します

@Override
    public int getItemViewType(int position) {
        return 1;
    }
3

私のコードはrecycleviewでUIをリセットするために働いています。

public class BooleanViewHolder extends BaseViewHolder<ConfigItemBoolean> {
    private SwitchCompat configBoolean;

    BooleanViewHolder(View view) {
        super(view);
        configBoolean = view.findViewById(R.id.enable_config_boolean);
        configBoolean.setOnCheckedChangeListener((buttonView, isChecked) -> {
            ((ConfigItemBoolean) getItem(getAdapterPosition())).setValue(isChecked);
            DataSet.mConfigDataSet.getConfigItemBooleanMap().put(configPairList.get(getAdapterPosition()).first, ((ConfigItemBoolean) getItem(getAdapterPosition())));
        });
    }

    @Override
    void bind(ConfigItemBoolean item, String key) {
        configBoolean.setText(item.getDisplayName());
        configBoolean.setChecked(item.isValue());
    }

}
1
May Yamin Thant