Декодер RecyclerView добавляет дополнительные дополнения при обновлении

Итак, у меня возникла странная проблема при реализации RecyclerView в моем проекте. У меня есть пользовательский декоратор для реализации согласованного верхнего и нижнего отступов и довольно иного значения заполнения между элементами. Всякий раз, когда я нажимаю на обновление, т.е. Извлекает данные из back-end и снова заполняет RecyclerView, добавление увеличивается и увеличивается при каждом обновлении.

This is the correct way

Когда я нажимаю обновление (вызывая повторное выполнение AsyncTask), пространство между элементами увеличивается. И он увеличивается с каждым обновлением.

Padding between items increasing

У меня типичное RecyclerView как это

<android.support.v7.widget.RecyclerView
    android:id="@+id/recyclerview"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:clickable="false"
    android:focusableInTouchMode="false">
</android.support.v7.widget.RecyclerView>

Заполнение содержимого внутри RecyclerView является CardView со следующим расположением:

<android.support.v7.widget.CardView
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:id="@+id/cv"
android:layout_marginLeft="9dp"
android:layout_marginRight="9dp"
>

    <RelativeLayout
        android:id="@+id/itemLinearTop"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:orientation="horizontal"
        android:paddingTop="17dp"
        android:paddingRight="10dp"
        android:paddingLeft="10dp">

        <TextView
            android:id="@+id/tv1"
            android:textColor="@color/logo_black"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:textAppearance="?android:attr/textAppearanceMedium" />


        <TextView
            android:id="@+id/tv2"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_alignBaseline="@+id/tv1"
            android:textColor="@color/logo_black"
            android:layout_alignParentRight="true"
            android:textAppearance="?android:attr/textAppearanceMedium" />

        <!-- More elements -->
    </RelativeLayout>
</android.support.v7.widget.CardView>

Я инициализирую и заполняю RecyclerView следующим образом:

// In PostExecute of AsyncTask
RecyclerView rv = (RecyclerView) rootView.findViewById(R.id.recyclerview);
RecycleViewAdapter adapter = new FuelPricesRecycleViewAdapter(data);
rv.setAdapter(adapter);
rv.addItemDecoration(new RecyclerViewItemDecoration(30, item_count - 1));

И вот мой класс RecyclerViewItemDecoration выглядит так:

public class RecyclerViewItemDecoration extends RecyclerView.ItemDecoration {
    private int space = 0;
    private int item_count = 0;
    private int ADDITIONAL_PADDING = 20;

    public RecyclerViewItemDecoration(int space, int item_count) {
        this.space = space;
        this.item_count = item_count;
    }

    @Override
    public void getItemOffsets(Rect outRect, View view, RecyclerView parent, RecyclerView.State state) {
        if(parent.getChildPosition(view) != item_count)
             outRect.bottom = space;

         // Add top margin only for the first item to avoid double space between items
         if(parent.getChildPosition(view) == 0)
             outRect.top = space + ADDITIONAL_PADDING;
         if(parent.getChildPosition(view) == item_count)
             outRect.bottom = space + ADDITIONAL_PADDING;
     }
 }

Спасибо за помощь!

Ответы

Ответ 1

Перед переустановкой новых данных необходимо удалить украшение элемента.

rv.removeItemDecoration(yourDecorator)

Дайте мне знать, если это сработает!

Ответ 2

Вы добавляете " Decoration каждый раз, когда загружается утилита.

Вместо этого используйте один флаг:

private boolean flagDecoration = false;

if(!flagDecoration)
{
    rv.addItemDecoration(new RecyclerViewItemDecoration(30, item_count - 1));
    flagDecoration = true;    
}

Ответ 3

Это происходит из-за того, что мы пытаемся добавить itemDecorator в представление рециркулятора, в которое уже добавлен itemDecorator, сначала проверьте, существует ли он, затем не добавляйте снова

if (0 == recyclerview.getItemDecorationCount()) {
recyclerview.addItemDecoration(new DividerItemDecoration(ContextCompat.getDrawable(getActivity(), R.drawable.divider)));
}

Это 0 будет номером itemDecorator, который у нас есть в представлении переработчика, в большинстве случаев это будет 0.

Ответ 4

У меня была та же проблема, и я исправил ее с помощью itemDecorationCount

if (recyclerView.itemDecorationCount == 0) {
            val itemDecorator = DividerItemDecoration(activity, DividerItemDecoration.VERTICAL)
            itemDecorator.setDrawable(ContextCompat.getDrawable(activity, R.drawable.recycler_divider))
            recyclerView.addItemDecoration(itemDecorator)
        }

Ответ 5

Я столкнулся с одной и той же проблемой, лучшим решением является сделать украшение вашего элемента, в то время как вы инициализируете свой менеджер макетов в держателе вида, это устраняет проблему, с которой вы сталкиваетесь

public class GridViewHolder extends ViewHolder {

    RecyclerView grid_list;

    public GridViewHolder(View v) {
        super(v);
        this.grid_list = (RecyclerView) v.findViewById(R.id.home_screen_item_grid_recycler_view);
        if (grid_list.getLayoutManager() == null) {
            RecyclerView.LayoutManager mLayoutManager = new GridLayoutManager(context, 4);
            grid_list.setLayoutManager(mLayoutManager);
            grid_list.addItemDecoration(new GridSpacingItemDecoration(4, 3, false));
        }
    }
}

Ответ 6

Столкнулся с той же проблемой и разрешил ее, разместив

mLayoutManager = new LinearLayoutManager(current_activity);
recyclerView.setLayoutManager(mLayoutManager);

в onPreExecute().

Просто попробуйте, если это сработает

Ответ 7

Я сталкиваюсь с той же проблемой. Исправьте его, если проверите

    if (recyclerView.getItemDecorationAt(0) == null) { // check decoration here
        FlexboxItemDecoration agentDividerItemDecoration = new FlexboxItemDecoration(rv.getContext());
        agentDividerItemDecoration.setDrawable(recyclerView.getContext().getResources().getDrawable(R.drawable.shape_divider_flex_normal));
        recyclerView.addItemDecoration(agentDividerItemDecoration);
    } else {
        Log.i(TAG, "initTagsView: ItemDecoration not null");
    }

Ответ 8

Видимо, вы добавляете различные украшения. У меня была такая же проблема. То, что я здесь делал и что получилось, было:

1º - Объявить декор перед методом onCreate():

public StickyHeaderDecoration mDecor;
public MyAdapterPinned MyAdapterPinned;

2º - Затем я создал метод, который создает и заполняет мой recycleview. В этом методе я проверяю, уже ли я назвал mDecor. Если это так, я удаляю его. В противном случае я создаю его. Код выглядит так:

public void createRecyclerView(){
    //hide layout com progress
    hideLayoutProgressFull();

    LinearLayoutManager mLayoutManager = new 
    LinearLayoutManager(getContext(), LinearLayoutManager.VERTICAL, false);
    recyclerView.setLayoutManager(mLayoutManager);

    recyclerView.setItemAnimator(new DefaultItemAnimator());

    myAdapterPinned = new MyAdapterPinned(getContext(), mList);

    recyclerView.setAdapter(myAdapterPinned);

    if (mDecor != null)
        recyclerView.removeItemDecoration(mDecor);

    mDecor = new StickyHeaderDecoration(myAdapterPinned);
    recyclerView.addItemDecoration(mDecor);

    //hide progressDialog
    hideProgress();
}    

ПРИМЕЧАНИЕ. Я использую адаптер, который устанавливает заголовок для каждого изменения, но вы не можете вмешиваться в результат. Вы можете использовать обычный адаптер. Это сработало для меня. Я надеюсь, что это сработает и для вас;