5

I have a NestedScrollView in which RecyclerView and a RelativeLayout lies inside..

It's basically this way

<NestedScrollView>

<RelativeLayout> //To contain the stuffs inside

    <RelativeLayout /> // Contains a `TextView` and a `ProgressBar`

    <RecyclerView /> // The most important thing.. Maybe

</RelativeLayout>

</NestedScrollView>

I am using a CustomLinearLayoutManager and recyclerView.setNestedScrollingEnabled(false); in order to scroll both RelativeLayout and RecyclerView together, else, only the RecyclerView will scroll, the RelativeLayout will just stay on top of it.

Whenever the RecyclerView loads new data, it freezes for 3-5 seconds which is very bad for user experience.. This is the CustomLayoutManager which I am using..

public class CustomLayoutManager extends LinearLayoutManager {

    public CustomLayoutManager(Context context) {
        super(context);
    }

    public CustomLayoutManager(Context context, int orientation, boolean reverseLayout) {
        super(context, orientation, reverseLayout);
    }

    public CustomLayoutManager(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
        super(context, attrs, defStyleAttr, defStyleRes);
    }

    private int[] mMeasuredDimension = new int[2];

    /**
     * Disable predictive animations. There is a bug in RecyclerView which causes views that
     * are being reloaded to pull invalid ViewHolders from the internal recycler stack if the
     * adapter size has decreased since the ViewHolder was recycled.
     */
    @Override
    public boolean supportsPredictiveItemAnimations() {
        return false;
    }

    @Override
    public void onMeasure(RecyclerView.Recycler recycler, RecyclerView.State state,
                          int widthSpec, int heightSpec) {
        final int widthMode = View.MeasureSpec.getMode(widthSpec);
        final int heightMode = View.MeasureSpec.getMode(heightSpec);
        final int widthSize = View.MeasureSpec.getSize(widthSpec);
        final int heightSize = View.MeasureSpec.getSize(heightSpec);
        int width = 0;
        int height = 0;
        for (int i = 0; i < getItemCount(); i++) {
            if (getOrientation() == HORIZONTAL) {
                measureScrapChild(recycler, i,
                        View.MeasureSpec.makeMeasureSpec(i, View.MeasureSpec.UNSPECIFIED),
                        heightSpec,
                        mMeasuredDimension);

                width = width + mMeasuredDimension[0];
                if (i == 0) {
                    height = mMeasuredDimension[1];
                }
            } else {
                measureScrapChild(recycler, i,
                        widthSpec,
                        View.MeasureSpec.makeMeasureSpec(i, View.MeasureSpec.UNSPECIFIED),
                        mMeasuredDimension);
                height = height + mMeasuredDimension[1];
                if (i == 0) {
                    width = mMeasuredDimension[0];
                }
            }
        }
        switch (widthMode) {
            case View.MeasureSpec.EXACTLY:
                width = widthSize;
            case View.MeasureSpec.AT_MOST:
            case View.MeasureSpec.UNSPECIFIED:
        }

        switch (heightMode) {
            case View.MeasureSpec.EXACTLY:
                height = heightSize;
            case View.MeasureSpec.AT_MOST:
            case View.MeasureSpec.UNSPECIFIED:
        }

        setMeasuredDimension(width, height);
    }

    private void measureScrapChild(RecyclerView.Recycler recycler, int position, int widthSpec,
                                   int heightSpec, int[] measuredDimension) {
        View view = recycler.getViewForPosition(position);
        recycler.bindViewToPosition(view, position);
        if (view != null) {
            RecyclerView.LayoutParams p = (RecyclerView.LayoutParams) view.getLayoutParams();
            int childWidthSpec = ViewGroup.getChildMeasureSpec(widthSpec,
                    getPaddingLeft() + getPaddingRight(), p.width);
            int childHeightSpec = ViewGroup.getChildMeasureSpec(heightSpec,
                    getPaddingTop() + getPaddingBottom(), p.height);
            view.measure(childWidthSpec, childHeightSpec);
            measuredDimension[0] = view.getMeasuredWidth() + p.leftMargin + p.rightMargin;
            measuredDimension[1] = view.getMeasuredHeight() + p.bottomMargin + p.topMargin;
            recycler.recycleView(view);
        }
    }
}

I actually only copied the CustomLayoutManager from another SO answer, it might be or might not be the problem..

Kevin Murvie
  • 2,240
  • 1
  • 18
  • 38
  • I think it is not because of CustomLayoutManager. I have the same problem with LinearLayoutManager. RecyclerView inside NestedScrollView works slow for me too. Here is a sample project which demonstrates differences in performance https://github.com/sirekanyan/android-recyclerview-inside-a-nestedscrollview (loading 1000 TextView items inside RecyclerView take several seconds on my device) – Vadik Jun 08 '16 at 12:53
  • 1
    In the end, I put everything inside RecyclerView by overriding `getItemViewType()`, I can set which item is placed in the position. This question was when I was a super newb at Android lol – Kevin Murvie Jun 09 '16 at 03:11

0 Answers0