问题
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