2016-04-16 2 views
0

У меня есть простой RecyclerView, который выглядит как список, я устанавливаю каждый вид разного ID и добавляя представления, нажимая на первое представление и удаляя представления, re click (ожидаем первый). То, что работает неправильно, - это когда я удаляю представление, а затем добавляю еще один, идентификатор нового представления нарушает порядок.Android: удаление и добавление просмотров в recyclerView должным образом

Адаптер

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()); 
       } 
      } 
     }); 
     } 
    } 
} 

Реализация:

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

    AddContainer.addItem(""); 

Схема для каждой строки:

<?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> 

Моя проблема в том, что если я добавлю 5 просмотров, удаляю второй, а затем добавлю еще один, он добавит второй снова isntead из 6-го. Итак, я думаю, вопрос в том, как не перерабатывать взгляды после их удаления?

+0

Что случилось с просто правильно используя 'onBindViewHolder' так как он предназначен? Ваш держатель вида должен * не * просто установить себя. –

+0

Я использую onBindViewHolder, чтобы установить текст каждого элемента, или вы говорите, что есть что-то, что я должен внести в него, которое не будет перерабатывать представления после удаления? –

+0

Я просто вижу, что вы устанавливаете текст в держателе вида при создании 'eventName.setText (String.format (" ", i));' Это, очевидно, не будет вызвано снова, что приведет к вашей проблеме. Привяжите свои объекты правильно в 'onBindViewHolder', и если вам нужен идентификатор, добавьте этот идентификатор в свою модель, а не ваш зритель –

ответ

1

Идея RecyclerViews является то, что держатель вид вы предоставите в onCreateViewHolder() могут быть повторно использованы для представлений одного и того же viewType. Такое поведение делает RecyclerViews эффективным - это дорого для раздувания просмотров и дорогостоящего запуска findViewById.

Вы не переопределили getItemViewType, так что ваш RecyclerView имеет только один вид - т. Е. Ваши ViewHolders могут быть переработаны между собой, когда вы просматриваете множество просмотров и удаляете/добавляете представления.

Так что происходит в вашем коде? Когда вы удаляете второй номер, его ViewHolder перерабатывается и отправляется обратно в пул просмотра ресайзера. Когда вы добавляете вид № 6, просмотр recycler использует переработанный держатель вида из числа 2. Таким образом, onCreateViewHolder никогда не вызывается (потому что был дополнительный просмотр для утилизации!). Однако onBindViewHolder-. Так добавить метод для обновления данных, отображаемых в 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); 
      } 
     } 
} 

и вызывать этот метод в onBindViewHolder:

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

Я получаю логику, она все еще не работает так, как предполагалось. Когда я удаляю представление, представления после этого меняют идентификатор на число, даже превосходящее количество просмотров, которые я уже добавил, чувствуют себя странно. –

+0

Не существует способа не перерабатывать представления после их удаления? –

+0

Причина, по которой ваш номер увеличивается, может заключаться в том, что у вас есть 'i' как статический int, который вы постоянно увеличиваете. Вы должны установить номер в представлении параметру позиции, который вы передаете setData (который передается из 'onBindViewHolder'()) –

0

Попробуйте изменить removeItem(int position) к

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

Это будет, скорее всего, решить ваш вопрос

+0

Это все еще беспорядочно, но, если я добавлю 5 просмотров и удаляю один, каждый вид после того, как я удалил, изменил его идентификатор на случайное число –

+0

, каково расположение вашего использования для вашего 'RecyclerView'? – Max

+0

RelativeLayout, я просто добавил его к вопросу –