Android: removing and adding views to a recyclerView properly

自作多情 提交于 2019-12-13 21:38:09

问题


I have a simple RecyclerView that looks like a list, I'm setting each view a diffrent ID, and adding views by clicking on the first view, and removing views when they're clicked (expect the first one). What's not working correctly is when I remove a view and then add another one, the new view's ID breaks the order.

The adapter

public class AddEventsAdapter extends RecyclerView.Adapter<AddEventsAdapter.ViewHolder> {

   private List<String> items = new ArrayList<>();

    public void addItem(String name) {
        items.add(name);
        notifyItemInserted(items.size() - 1);
    }

    public void removeItem(int position) {
        items.remove(position);
        notifyItemRemoved(position);
    }

    @Override
    public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
        LayoutInflater inflater = LayoutInflater.from(parent.getContext());
        View view = inflater.inflate(R.layout.add_event_item, parent, false);

        return new ViewHolder(view);
    }

    @Override
    public void onBindViewHolder(ViewHolder holder, int position) {
    }

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

    static int i;

    class ViewHolder extends RecyclerView.ViewHolder{

        public TextView eventName;
        public RelativeLayout theLayout;


        public ViewHolder(View itemView) {
            super(itemView);
            eventName = (TextView)itemView.findViewById(R.id.eventName);
            theLayout = (RelativeLayout)itemView.findViewById(R.id.backgroundevent);

            theLayout.setId(++i);
            eventName.setText(String.format("", i));

            theLayout.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                if (v.getId() == 1){
                    addItem("");
                }else {
                    removeItem(getAdapterPosition());
                }
            }
        });
        }
    }
}

The implementation:

    final AddEventsAdapter AddContainer = new AddEventsAdapter();
    AddEventsRecycler.setLayoutManager(new LinearLayoutManager(this));
    AddEventsRecycler.setAdapter(AddContainer);
    AddEventsRecycler.setItemViewCacheSize(666);

    AddContainer.addItem("");

The layout for every row:

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:background="@drawable/event_clicked_ripple"
    android:clickable="true"
    android:id="@+id/backgroundevent"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:padding="10dp">

    <TextView
        android:clickable="false"
        android:id="@+id/eventName"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="something"
        android:layout_centerVertical="true"
        android:layout_toLeftOf="@+id/eventImage"
        android:layout_toStartOf="@+id/eventImage"
        android:layout_marginRight="10dp"/>

    <ImageButton
        android:clickable="false"
        android:id="@+id/eventImage"
        android:layout_alignParentEnd="true"
        android:layout_alignParentRight="true"
        android:layout_width="30dp"
        android:layout_height="30dp"
        android:background="@drawable/oval_shape"/>

</RelativeLayout>

My problem is, if I add 5 views, remove the 2nd, and then add another one, it will add the 2nd again isntead of a 6th. So I think the question here is how to not recycle the views after removing them?


回答1:


The idea behind RecyclerViews is that the view holder you provide in onCreateViewHolder() may be reused for views of the same viewType. This behavior is what makes RecyclerViews efficient - it is expensive to inflate views, and expensive to run findViewById.

You did not override getItemViewType so your RecyclerView only has one viewtype -- i.e. your ViewHolders are free to be recycled amongst each other as you scroll across many views, and delete/add views.

So what is happening in your code? When you delete view number two, its ViewHolder is recycled, and sent back to the recycler view pool. When you add view number 6, the recycler view uses the recycled view holder from number 2. Thus, onCreateViewHolder is never called (because there was an extra view to recycle!). However, onBindViewHolder is called. So add a method to update the data displayed by the ViewHolder:

 public void setData(final int position) {
    eventName.setText(String.format("", position));
    theLayout.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View v) {
            if (position == 1){
                addItem("");
            }else {
                removeItem(position);
            }
        }
}

and call this method in onBindViewHolder:

@Override
public void onBindViewHolder(ViewHolder holder, int position) {
     holder.setData(position);
}



回答2:


Try changing your removeItem(int position) to

public void removeItem(int position) {
    items.remove(position);
    notifyItemRemoved(position);
    notifyItemRangeChanged(position, items.size());
}

It will most probably solve your issue



来源:https://stackoverflow.com/questions/36666982/android-removing-and-adding-views-to-a-recyclerview-properly

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!