如何正确处理RecyclerView ViewHolder内部的膨胀视图



我有多个布局将在我的RecyclerViewViewHolder中膨胀,视图的膨胀取决于传递给ViewHolder的数据集,我知道如何使用getItemViewType(),但在我的情况下它不适用,因此例如,数据集包含1,2,3,它将把所有视图膨胀到ViewHolder容器(LinearLayout(。

带有LinearLayout容器的我的ViewHolder:

<android.support.v7.widget.CardView 
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:card_view="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="wrap_content"
card_view:cardBackgroundColor="@android:color/white"
card_view:cardCornerRadius="2dp"
card_view:cardElevation="2dp">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical">
<include layout="@layout/layout_header" />
<LinearLayout
android:id="@+id/lnr_container"     
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical">
</LinearLayout>
<include layout="@layout/layout_footer" />
</LinearLayout>
</android.support.v7.widget.CardView>

ViewHolder1:

在这里,我用变量创建了一个视图的引用,如果视图被回收,我只会检查变量是否不为null,例如recyclerView,我只重置数据。

private class ViewHolder1 extends RecyclerView.ViewHolder{
@BindView(R.id.lnr_container)
LinearLayout mLnrContainer;
private RecyclerView mRecyclerView;
private ImageView mImageView;
private LinearLayout mLayout;
public ViewHolder1(View itemView) {
super(itemView);
ButterKnife.bind(this,itemView);
}
public void setData(JSONObject data){
mLnrContainer.removeAllViews();
if (data.has("1")){
if (mRecyclerView == null){
mRecyclerView  = new RecyclerView(itemView.getContext());
// other implementation
mRecyclerView.setAdapter(new SomeAdapter(itemView.getContext(),data));
}else {
mRecyclerView.getAdapter().setData(data);
}
addView(mRecyclerView);
}
if (data.has("2")){
mImageView  = new ImageView(itemView.getContext());
addView(mImageView);
}
if (data.has("3")){
mLayout = LayoutInflater.from(itemView.getContext()).inflate(R.layout.custom_layout,mLnrContainer,false);
addView(mLayout);
}
}
private void addView(View view){
mLnrContainer.addView(view);
}
}

ViewHolder2:

private class ViewHolder2 extends RecyclerView.ViewHolder{
@BindView(R.id.lnr_container)
LinearLayout mLnrContainer;
public ViewHolder2(View itemView) {
super(itemView);
ButterKnife.bind(this,itemView);
}
public void setData(JSONObject data){
mLnrContainer.removeAllViews();
if (data.has("1")){
RecyclerView mRecyclerView  = new RecyclerView(itemView.getContext(),data);
addView(mRecyclerView);
}
if (data.has("2")){
ImageView mImageView  = new ImageView(itemView.getContext());
addView(mImageView);
}
if (data.has("3")){
LinearLayout  mLayout = LayoutInflater.from(itemView.getContext()).inflate(R.layout.custom_layout,mLnrContainer,false);
addView(mLayout);
}
}
private void addView(View view){
mLnrContainer.addView(view);
}
}

我想知道并困惑于这些ViewHolder中的哪一个应该在我的代码中实现,如果ViewHolder被回收,会有什么不同吗?谢谢你的回答和建议。

ViewHolder是专门为防止过度膨胀而制作的,在onBind中这样做会导致性能非常差。

我会使用多个itemViewType,并相应地扩展布局,只是为了至少有一些东西可以回收。如果这些"1、2、3"不是互斥的,则会给出8种不同的布局组合。

修改您的RecyclerView.Adapter以反映可能的组合:

private static final int VIEWTYPE_FLAG_HAS_RECYCLER = 1;
private static final int VIEWTYPE_FLAG_HAS_IMAGEVIEW = 1 << 1;
private static final int VIEWTYPE_FLAG_HAS_LINEAR = 1 << 2;
// shared view pool
private final RecyclerView.RecycledViewPool adapterSharedRecycledViewPool = new RecyclerView.RecycledViewPool();
@Override
public int getItemViewType(int position) {
JSONObject data = dataList.get(position);
int viewType = 0;
// each type is a flag in viewType int, this returns values from 0 to 7
if(data.has("1"))
viewType = VIEWTYPE_FLAG_HAS_RECYCLER;
if(data.has("2"))
viewType |= VIEWTYPE_FLAG_HAS_IMAGEVIEW;
if(data.has("3"))
viewType |= VIEWTYPE_FLAG_HAS_LINEAR;
return viewType;
}

然后在创建viewholder时检查标志(例如,将viewType作为构造函数参数传递(:

private class ViewHolder3 extends RecyclerView.ViewHolder{
@BindView(R.id.lnr_container)
LinearLayout mLnrContainer;
private RecyclerView mRecyclerView;
private ImageView mImageView;
private LinearLayout mLayout;
public ViewHolder3(View itemView, int viewType) {
super(itemView);
ButterKnife.bind(this,itemView);
// only need to inflate extra views once
if((viewType & VIEWTYPE_FLAG_HAS_RECYCLER) > 0){
mRecyclerView  = new RecyclerView(itemView.getContext());
// adapter must handle empty dataset
mRecyclerView.setAdapter(new SomeAdapter(itemView.getContext(), null));
// optimization to share views between other items
mRecyclerView.setRecycledViewPool(adapterSharedRecycledViewPool);
addView(mRecyclerView);
}
if((viewType & VIEWTYPE_FLAG_HAS_IMAGEVIEW) > 0){
mImageView  = new ImageView(itemView.getContext());
addView(mImageView);
}
if((viewType & VIEWTYPE_FLAG_HAS_LINEAR) > 0){
mLayout = LayoutInflater.from(itemView.getContext()).inflate(R.layout.custom_layout,mLnrContainer,false);
addView(mLayout);
}
}
public void setData(JSONObject data){
// views must be ready now
if (data.has("1")){
mRecyclerView.getAdapter().setData(data);
}
if (data.has("2")){
// bind image view if needed
}
if (data.has("3")){
// bind data to linear layout as needed
}
}
private void addView(View view){
mLnrContainer.addView(view);
}
}

请注意setRecycledViewPool:这允许嵌套的回收器视图共享由其他嵌套回收器视图创建的视图。这将提高性能,但someAdapter创建的ViewHolders必须是一个静态类(而不是适配器的内部类(,因为这允许ViewHolders在不同的RecyclerViews/Adapters之间遍历。

最新更新