Recycler View不保存视图状态

问题描述 投票:4回答:3

我正在使用Recycler视图,其中我在适配器中使用LinearLayout。单击LinearLayout时,它隐藏了View,同样再次点击使其变为可见。我的问题是Recycler视图没有持有Views的状态,当我滚动时它再次刷新View再次改变状态视图的初始时间。

我的RecyclerView代码以及我的适配器如下所示。

RecyclerView代码:

 LinearLayoutManager layoutManager = new LinearLayoutManager(getActivity());
  Menu_Detail_Adapter  searchabledapter = new Menu_Detail_Adapter(getActivity());
   RecyclerView mRecyclerView =(RecyclerView)view.findViewById(R.id.recycler_view);
    mRecyclerView.setHasFixedSize(true);
    mRecyclerView.setItemViewCacheSize(2);
    mRecyclerView.setAdapter(searchabledapter);
    mRecyclerView.setLayoutManager(layoutManager);

我的适配器代码:

public class Menu_Detail_Adapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> implements Filterable {


    public Menu_Detail_Adapter(Context context1) {
        arrayList = new ArrayList<>();
        arrlist = new ArrayList<>();
        context = context1;
    }




    @Override
    public RecyclerView.ViewHolder  onCreateViewHolder(ViewGroup parent, int viewType) {


            View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.kasib_o_karahi_list_view, parent, false);
            return new MemberViewHolder(view, onItemClickListener);

    }



    String imageUrl = "";
    @Override
    public void onBindViewHolder(final RecyclerView.ViewHolder  holder, int position) {

        final ParseObject parseObject = arrayList.get(position);

        if(holder instanceof  MemberViewHolder){

            if (arrayList.size() > 0) {
                try {

                    ((MemberViewHolder) holder).linear_layout__add.setVisibility(View.VISIBLE);
                    ((MemberViewHolder) holder).linear_layout_add_subtract_buttons.setVisibility(View.GONE);

                    // Here I am facing a problem

                    // On both LinearLayout click listeners when I am scrolling it 
is again changing my View States


                    ((MemberViewHolder) holder).rrl_add.setOnClickListener(new View.OnClickListener() {
                        @Override
                        public void onClick(View view) {
                            ((MemberViewHolder) holder).linear_layout__add.setVisibility(View.GONE);
                            ((MemberViewHolder) holder).linear_layout_add_subtract_buttons.setVisibility(View.VISIBLE);
                        }
                    });

                    ((MemberViewHolder) holder).rrl_minus.setOnClickListener(new View.OnClickListener() {
                        @Override
                        public void onClick(View view) {
                            ((MemberViewHolder) holder).linear_layout__add.setVisibility(View.VISIBLE);
                            ((MemberViewHolder) holder).linear_layout_add_subtract_buttons.setVisibility(View.GONE);
                        }
                    });

                    ((MemberViewHolder) holder).rrl_add_btn.setOnClickListener(new View.OnClickListener() {
                        @Override
                        public void onClick(View view) {

                        }
                    });



                } catch (Exception e) {
                    e.getMessage();
                }
            }
        }
    }

    @Override
    public int getItemCount() {
        return arrayList == null ? 0 : arrayList.size();
    }

    @Override
    public void onAttachedToRecyclerView(RecyclerView recyclerView) {
        super.onAttachedToRecyclerView(recyclerView);
    }

    @Override
    public void onDetachedFromRecyclerView(RecyclerView recyclerView) {
        super.onDetachedFromRecyclerView(recyclerView);
    }




    static class MemberViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener {

        TextView txtTitle;
        TextView txtDescription;
        TextView txtCountry;
        OnItemClickListener onItemClickListener;
        ImageView imgDescription;

        LinearLayout linear_layout_add_subtract_buttons, linear_layout__add;
        RelativeLayout rrl_add, rrl_minus, rrl_add_btn;

        public MemberViewHolder(View itemView, OnItemClickListener onItemClickListener) {
            super(itemView);
            linear_layout_add_subtract_buttons = (LinearLayout) itemView.findViewById(R.id.add_subtract_buttons);
            linear_layout__add                 = (LinearLayout) itemView.findViewById(R.id.ll_add);
            rrl_add              = (RelativeLayout) itemView.findViewById(R.id.rrl_add);
            rrl_minus            = (RelativeLayout) itemView.findViewById(R.id.rrl_minus);
            rrl_add_btn          = (RelativeLayout) itemView.findViewById(R.id.rrl_add_btn);


            itemView.setOnClickListener(this);
            this.onItemClickListener = onItemClickListener;
        }

        @Override
        public void onClick(View v) {
            onItemClickListener.onItemClick(v, getAdapterPosition());
        }
    }

    public interface OnItemClickListener {
        void onItemClick(View view, int position);
    }

    public void setOnItemClickListener(OnItemClickListener onItemClickListener) {
        this.onItemClickListener = onItemClickListener;
    }


}
android android-recyclerview adapter
3个回答
2
投票

一个问题是您的代码既不简单也不完整且可验证。所以我不得不做一个你必须根据自己的需要采用的例子。

我所谈论的“单一对象阵列”由DataItem类的对象组成,其中包含一个int和两个booleans成员。

public class DataItem{
    int dataItem;
    boolean visible1;
    boolean visible2;

    public DataItem(int dataItem, boolean visible1, boolean visible2){
        this.dataItem = dataItem;
        this.visible1 = visible1;
        this.visible2 = visible2;
    }
}

我活动中的onCreate()看起来像这样:

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity);

    int dataItemsLength = 50;
    ArrayList<DataItem> dataItems = new ArrayList<>();
    for (int i = 0; i < dataItemsLength; i++) {
        dataItems.add(new DataItem(i, true, true));
    }
    RecyclerView rv = findViewById(R.id.rv);
    Menu_Detail_Adapter adapter = new Menu_Detail_Adapter(this, dataItems);
    rv.setLayoutManager(new LinearLayoutManager(this));
    rv.setAdapter(adapter);
}

虽然在你的代码中不清楚你的数据来自何处,但在这里我选择了在活动中“制作”数据(你可能想要“读取”它)并将其传递给适配器的方法。原则上,您也可以在适配器中执行此操作。

我为RecyclerView使用了一个非常简单的布局:

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="wrap_content">

    <android.support.v7.widget.RecyclerView
        android:id="@+id/rv"
        android:layout_width="match_parent"
        android:layout_height="wrap_content" />

</RelativeLayout>

并且项目的布局只是稍微复杂一些:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:orientation="vertical">

    <RelativeLayout
        android:id="@+id/rl1"
        android:layout_width="match_parent"
        android:layout_height="25dp"
        android:background="@android:color/holo_orange_light">

       <TextView
            android:id="@+id/tv1"
            android:layout_width="match_parent"
            android:layout_height="match_parent" />
    </RelativeLayout>

    <RelativeLayout
        android:id="@+id/rl2"
        android:layout_width="match_parent"
        android:layout_height="25dp"
        android:background="@android:color/holo_orange_dark">

        <TextView
            android:id="@+id/tv2"
            android:layout_width="match_parent"
            android:layout_height="match_parent" />
    </RelativeLayout>
</LinearLayout>

最重要的是,适配器:

public class Menu_Detail_Adapter extends RecyclerView.Adapter<Menu_Detail_Adapter.ViewHolder> {
    private ArrayList<DataItem> dataItems;
    private final LayoutInflater inflater;

    Menu_Detail_Adapter(Context context, ArrayList<DataItem> dataItems) {
        this.dataItems = new ArrayList<>();
        this.dataItems.addAll(dataItems);
        this.inflater = LayoutInflater.from(context);
    }

    @Override
    public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
        return new ViewHolder(inflater.inflate(R.layout.list_item, parent, false));
    }

    @Override
    public void onBindViewHolder(ViewHolder holder, int position) {
        holder.rl1.setVisibility(dataItems.get(position).visible1 ? View.VISIBLE : View.INVISIBLE);
        holder.tv1.setText(String.valueOf(dataItems.get(position).dataItem));
        holder.rl2.setVisibility(dataItems.get(position).visible2 ? View.VISIBLE : View.INVISIBLE);
    }

    @Override
    public int getItemCount() {
        return dataItems.size();
    }

    public class ViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener {
        RelativeLayout rl1, rl2;
        TextView tv1;

        ViewHolder(View itemView) {
            super(itemView);
            rl1 = itemView.findViewById(R.id.rl1);
            rl2 = itemView.findViewById(R.id.rl2);
            rl1.setOnClickListener(this);
            rl2.setOnClickListener(this);
            tv1 = itemView.findViewById(R.id.tv1);
            ((TextView) itemView.findViewById(R.id.tv2)).setText("default");
        }

        @Override
        public void onClick(View view) {
            if (view.getId() == R.id.rl1) {
                if (view.getVisibility() == View.VISIBLE) {
                    view.setVisibility(View.INVISIBLE);
                    dataItems.get(getAdapterPosition()).visible1 = false;
                } else {
                    view.setVisibility(View.VISIBLE);
                    dataItems.get(getAdapterPosition()).visible1 = true;
                }
            } else if (view.getId() == R.id.rl2) {
                if (view.getVisibility() == View.VISIBLE) {
                    view.setVisibility(View.INVISIBLE);
                    dataItems.get(getAdapterPosition()).visible2 = false;
                } else {
                    view.setVisibility(View.VISIBLE);
                    dataItems.get(getAdapterPosition()).visible2 = true;
                }
            }
        }
    }
}

关于适配器的一些评论:

  • 确保不要对onBindViewHolder()中的任何可见性进行硬编码。请改用您的数据集。
  • onClickListeners附加到ViewHolder类的构造函数中。如果您愿意,可以将侦听器添加为匿名类,并避免使用统一的onClick方法的if子句。这主要是品味问题。
  • 在侦听器内部,请小心两者:刷新视图并更新模型。这是至关重要的一点。
  • 为了您的目的,请不要使用notifyDataSetChanged。这只是必要的,如果你从DateItem中添加或删除ArrayList<DataItem>,称为dataItems

1
投票

也许你可以创建第二个arrayList,默认情况下使用一个包含2个布尔值的对象。然后每次更改为GONE或VISIBLE时,都会更改布尔值。

初始化视图时,您将为第二个arraylist提供与当前arrayList相同的大小。

在onBindviewHolder中,您可以根据布尔状态设置可见性(因此默认情况下它将为true),然后在onClickListener上更改布尔值。


0
投票

当您希望项状态依赖于动态值更改时,您可能需要考虑将该值放入对象(来自数组)本身,并使用它而不是依赖于视图持有者缓存的内存

© www.soinside.com 2019 - 2024. All rights reserved.