OnCreateViewHolder RecyclerView.Adapter вызывается дважды или более, несколько раз

В настоящее время я разрабатываю приложение, которое использует RecyclerView.

При рассмотрении LogCat я заметил, что onCreateViewHolder вызывается дважды после его создания.

09-22 05:22:55.209 V/Adapter﹕ Construct
09-22 05:22:55.213 V/Adapter﹕ onCreateViewHolder
09-22 05:22:55.224 V/Adapter﹕ onBindViewHolder
09-22 05:22:55.240 V/Adapter﹕ onCreateViewHolder
09-22 05:22:55.247 V/Adapter﹕ onBindViewHolder

Также onBindViewHolder вызывается дважды, хотя я знаю, что он вызывается всякий раз, когда элементы перерабатываются.

Но я думаю, что для onCreateViewHolder достаточно вызвать один раз.

Это ненормальное поведение? Если да, то как это можно исправить?

Ответ 1

Это не ненормальное, но вполне нормальное поведение. Вам не нужно беспокоиться.

Верно, что ViewHolder будет переработан и не будет повторно создан повторно.

Однако для отображения нескольких элементов на экране приложения требуется несколько ViewHolders. Таким образом, будет создано определенное количество ViewHolders, и для этого onCreateViewHolder вызывается определенное время.

И onBindViewHolder будет вызываться бесконечно всякий раз, когда данные reset относятся к одному из ViewHolders.

Я рассмотрел этот факт с тестовым приложением, как показано ниже:

MainActivity:

public class MainActivity extends AppCompatActivity {
    private static final String[] DATASET = new String[]{
            "a", "b", "c", "d", "e", "f", "g", "h", "i", "j", "k", "l", "m",
            "n", "o", "p", "q", "r", "s", "t", "u", "v", "w", "x", "y", "z",
    };

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

        RecyclerView recyclerView = (RecyclerView) findViewById(R.id.recycler_view);
        recyclerView.setHasFixedSize(true);

        LinearLayoutManager layoutManager = new LinearLayoutManager(this);
        recyclerView.setLayoutManager(layoutManager);

        MyAdapter myAdapter = new MyAdapter(DATASET);
        recyclerView.setAdapter(myAdapter);
    }
}

MyAdapter:

public class MyAdapter extends RecyclerView.Adapter<MyAdapter.ViewHolder> {
    private static final String LOG_TAG = "RecyclerViewAdapter";
    private String[] dataset;

    private int counterOnCreateViewHolder = 0;
    private int counterOnBindViewHolder = 0;

    public MyAdapter(String[] dataset) {
        Log.d(LOG_TAG, "Construct");
        this.dataset = dataset;
    }

    public static class ViewHolder extends RecyclerView.ViewHolder {
        public TextView textView;
        public ViewHolder(TextView textView) {
            super(textView);
            this.textView = textView;
        }
    }

    @Override
    public MyAdapter.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
        Log.d(LOG_TAG, "onCreateViewHolder (" + ++counterOnCreateViewHolder + ")");
        View view = LayoutInflater.from(parent.getContext())
                .inflate(R.layout.adapter_textview, parent, false);

        ViewHolder viewHolder = new ViewHolder((TextView) view);
        return viewHolder;
    }

    @Override
    public void onBindViewHolder(ViewHolder holder, int position) {
        Log.d(LOG_TAG, "onBindViewHolder (" + ++counterOnBindViewHolder + ")");
        holder.textView.setText(dataset[position]);
    }

    @Override
    public int getItemCount() {
        // Log.d(LOG_TAG, "getItemCount");
        return dataset.length;
    }
}

Макет/activity_main.xml:

<android.support.v7.widget.RecyclerView
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:scrollbars="vertical"
    android:id="@+id/recycler_view" />

Макет/adapter_textview.xml:

<TextView
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:id="@+id/adapter_textview"
    android:textSize="30sp" />

Результат:

09-22 06:03:04.166 D/RecyclerViewAdapter﹕ Construct
09-22 06:03:05.179 D/RecyclerViewAdapter﹕ onCreateViewHolder (1)
09-22 06:03:05.183 D/RecyclerViewAdapter﹕ onBindViewHolder (1)
09-22 06:03:05.190 D/RecyclerViewAdapter﹕ onCreateViewHolder (2)
09-22 06:03:05.192 D/RecyclerViewAdapter﹕ onBindViewHolder (2)
09-22 06:03:05.192 D/RecyclerViewAdapter﹕ onCreateViewHolder (3)
09-22 06:03:05.194 D/RecyclerViewAdapter﹕ onBindViewHolder (3)
09-22 06:03:05.195 D/RecyclerViewAdapter﹕ onCreateViewHolder (4)
09-22 06:03:05.197 D/RecyclerViewAdapter﹕ onBindViewHolder (4)
09-22 06:03:05.198 D/RecyclerViewAdapter﹕ onCreateViewHolder (5)
09-22 06:03:05.199 D/RecyclerViewAdapter﹕ onBindViewHolder (5)
09-22 06:03:05.200 D/RecyclerViewAdapter﹕ onCreateViewHolder (6)
09-22 06:03:05.202 D/RecyclerViewAdapter﹕ onBindViewHolder (6)
09-22 06:03:05.203 D/RecyclerViewAdapter﹕ onCreateViewHolder (7)
09-22 06:03:05.204 D/RecyclerViewAdapter﹕ onBindViewHolder (7)
09-22 06:03:05.206 D/RecyclerViewAdapter﹕ onCreateViewHolder (8)
09-22 06:03:05.207 D/RecyclerViewAdapter﹕ onBindViewHolder (8)
09-22 06:03:05.209 D/RecyclerViewAdapter﹕ onCreateViewHolder (9)
09-22 06:03:05.211 D/RecyclerViewAdapter﹕ onBindViewHolder (9)
09-22 06:03:05.212 D/RecyclerViewAdapter﹕ onCreateViewHolder (10)
09-22 06:03:05.213 D/RecyclerViewAdapter﹕ onBindViewHolder (10)
09-22 06:03:05.215 D/RecyclerViewAdapter﹕ onCreateViewHolder (11)
09-22 06:03:05.217 D/RecyclerViewAdapter﹕ onBindViewHolder (11)
09-22 06:03:05.218 D/RecyclerViewAdapter﹕ onCreateViewHolder (12)
09-22 06:03:05.220 D/RecyclerViewAdapter﹕ onBindViewHolder (12)
09-22 06:03:55.048 D/RecyclerViewAdapter﹕ onCreateViewHolder (13)
09-22 06:03:55.050 D/RecyclerViewAdapter﹕ onBindViewHolder (13)
09-22 06:03:55.228 D/RecyclerViewAdapter﹕ onCreateViewHolder (14)
09-22 06:03:55.229 D/RecyclerViewAdapter﹕ onBindViewHolder (14)
09-22 06:03:55.230 D/RecyclerViewAdapter﹕ onCreateViewHolder (15)
09-22 06:03:55.231 D/RecyclerViewAdapter﹕ onBindViewHolder (15)
09-22 06:03:55.232 D/RecyclerViewAdapter﹕ onBindViewHolder (16)
09-22 06:03:55.232 D/RecyclerViewAdapter﹕ onBindViewHolder (17)
09-22 06:03:55.260 D/RecyclerViewAdapter﹕ onBindViewHolder (18)
09-22 06:03:55.276 D/RecyclerViewAdapter﹕ onBindViewHolder (19)
09-22 06:03:55.296 D/RecyclerViewAdapter﹕ onBindViewHolder (20)
09-22 06:03:55.310 D/RecyclerViewAdapter﹕ onBindViewHolder (21)

Как вы можете видеть, после onCreateViewHolder (15) вызывается только onBindViewHolder.

Ответ 2

Вы можете увеличить счет RecycledViewPool с помощью этого кода. По умолчанию он имеет 5.

вы можете увеличить в соответствии с вашими потребностями.

recyclerView.getRecycledViewPool(). setMaxRecycledViews (0,50);//0 - тип вашего представления

Ответ 3

Вот стабильный ответ на стабильные представления для RecyclerView

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

  1. mRecyclerview.getRecycledViewPool(). setMaxRecycledViews (int viewtype, int itemsCount)

  2. mRecyclerview.setItemViewCacheSize(int itemsCount)

    Оба метода помогают не перерабатывать вертикальные виды. Но если список слишком велик, это приведет к ошибке OOM, поэтому будьте осторожны при его реализации.

    Here 0 is viewType in Recyclerview adapter and 10 are the items count.
    
    mRecyclerview.getRecycledViewPool().setMaxRecycledViews(0, 10);
    mRecyclerview.setItemViewCacheSize(10);