V
V
Vadim Prokhorov2016-09-27 01:14:17
Android
Vadim Prokhorov, 2016-09-27 01:14:17

Why doesn't the onCreateViewHolder method always get called in the RecyclerView adapter?

I have an adapter for RecyclerView with the ability to add two different views (view, progress).
The implementation code of the onCreateViewHolder method:

//--Создание View--//
    @Override
    public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
        RecyclerView.ViewHolder viewHolder;
        if (viewType == POST_CARD_VIEW) {
            Log.d("TEST:", "onCreateViewHolder POST:" + test1);
            View view = inflater.inflate(R.layout.post_card, parent, false);
            viewHolder = new ViewHolderPost(view);
            test1 ++;
        }
        else {
            Log.d("TEST:", "onCreateViewHolder PROGRESS:" + test2);
            View view = inflater.inflate(R.layout.progres_bar, parent, false);
            viewHolder = new ProgressViewHolder(view);
            test2++;
        }
        return viewHolder;
    }

Implementation code of the onBindViewHolder method:
//--Метод onBind--//
    @Override
    public void onBindViewHolder(RecyclerView.ViewHolder holder, final int position) {
        if (holder instanceof ViewHolderPost) {
            Log.d("TEST:", "onBindViewHolder POST:" + test3);
            holder.itemView.setTag(mData.get(position));
            holder.itemView.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View view) {
                    Log.d("TEST:", "OnClick on Post: " + position);
                }
            });
            addData((ViewHolderPost) holder, mData.get(position));
            test3++;
            Log.d("TEST:", "------------------------------------------------------------------------");
        }
        else {
            Log.d("TEST:", "onBindViewHolder PROGRESS:" + test4);
            ((ProgressViewHolder) holder).progressBar.setIndeterminate(true);
            test4++;
            Log.d("TEST:", "------------------------------------------------------------------------");
        }
    }

Container layout for RecyclerView:
<FrameLayout
            android:id="@+id/container" <!--Контейнер для RecyclerView-->
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:layout_below="@+id/appBarLayout"
            app:layout_behavior="@string/appbar_scrolling_view_behavior">

            <android.support.v4.widget.NestedScrollView
                xmlns:android="http://schemas.android.com/apk/res/android"
                android:id="@+id/mScrollingContent"
                android:layout_width="match_parent"
                android:layout_height="match_parent"
                android:background="#EEEEEE"
                android:isScrollContainer="false"
                android:theme="@style/AppTheme"
                app:layout_behavior="@string/appbar_scrolling_view_behavior">

            </android.support.v4.widget.NestedScrollView>
        </FrameLayout>

Suppose I passed 10 views to the adapter, everything is fine with them, they are displayed (in this case, they are created as they appear on the screen), but when scrolling up to 6 views, the onCreateViewHolder method stops being called, while the onBindViewHolder method is called as you scroll further:
D/TEST:: onCreateViewHolder PROGRESS:0
D/TEST:: onBindViewHolder PROGRESS:0
D/TEST:: -----------------------------------------------------------------------
D/TEST:: onCreateViewHolder POST:0
D/TEST:: onBindViewHolder POST:0
D/TEST:: -----------------------------------------------------------------------
D/TEST:: onCreateViewHolder POST:1
D/TEST:: onBindViewHolder POST:1
D/TEST:: -----------------------------------------------------------------------
D/TEST:: onCreateViewHolder POST:2
D/TEST:: onBindViewHolder POST:2
D/TEST:: -----------------------------------------------------------------------
D/TEST:: onCreateViewHolder POST:3
D/TEST:: onBindViewHolder POST:3
D/TEST:: -----------------------------------------------------------------------
D/TEST:: onCreateViewHolder POST:4
D/TEST:: onBindViewHolder POST:4
D/TEST:: -----------------------------------------------------------------------
D/TEST:: onCreateViewHolder POST:5
D/TEST:: onBindViewHolder POST:5
D/TEST:: -----------------------------------------------------------------------
D/TEST:: onBindViewHolder POST:6
D/TEST:: -----------------------------------------------------------------------
D/TEST:: onBindViewHolder POST:7
D/TEST:: -----------------------------------------------------------------------
D/TEST:: onBindViewHolder POST:8
D/TEST:: -----------------------------------------------------------------------
D/TEST:: onBindViewHolder POST:9
D/TEST:: -----------------------------------------------------------------------

The onScrolled method is overridden, but that it is empty, that with logic, the situation does not change.
If we make the NestedScrollView a container for the RecyclerView and remove the FrameLayout, the error will disappear (because onScrolled is not called) and all 10 views will be created at once.
And since photos are loaded in the onBindViewHolder method, it turns out that the view number 1 can have photos of views number 10, 4, 6, 1 ... all at once (in the method dynamic creation of ImageView).
What did I do wrong? Maybe something is missing?

Answer the question

In order to leave comments, you need to log in

1 answer(s)
D
Denis Zagaevsky, 2016-09-27
@Vadik052

So that's the point of a recycler. It reuses views. In your opinion, if there are 100 of them, he should create 100 views? No.

Didn't find what you were looking for?

Ask your question

Ask a Question

731 491 924 answers to any question