Shabbir Dhangot
Shabbir Dhangot

Reputation: 9121

Multiple RecyclerView inside NestedScrollView Performance issue

I am facing performance issue while adding multiple RecyclerView inside NestedScrollView. I am displaying two horizontal on top and vertical RecyclerView on bottom.

I have Added below line

recyclerView.setNestedScrollingEnabled(false);

This is showing all list properly but real question is I am facing performance issue.

All three RecyclerView is showing after ~5 sec of all response come. This is also blocking UI as it busy for RecyclerView to appear.

XML

<android.support.v4.widget.NestedScrollView
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:layout_below="@+id/llTabs"
    android:fillViewport="true"
    app:layout_behavior="@string/appbar_scrolling_view_behavior">

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:orientation="vertical">

        <com.turacomobile.gb.utils.CustomSFUIMediumTextView
            android:id="@+id/tvMyBrands"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:padding="8dp"
            android:text="My Streamz (Brands)"
            android:textColor="@color/black" />

        <android.support.v7.widget.RecyclerView
            android:id="@+id/rvMyBrands"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:orientation="horizontal"
            android:paddingLeft="@dimen/dimen_5dp"
            android:paddingRight="@dimen/dimen_5dp"
            app:layout_behavior="@string/appbar_scrolling_view_behavior" />

        <com.turacomobile.gb.utils.CustomSFUIMediumTextView
            android:id="@+id/tvRecommendedBrands"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:padding="8dp"
            android:text="Recommended Streamz (Brands)"
            android:textAppearance="@style/TabLayoutTextStyleSearch"
            android:textColor="@color/black" />

        <android.support.v7.widget.RecyclerView
            android:id="@+id/rvRecommendedBrands"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:orientation="horizontal"
            android:paddingLeft="@dimen/dimen_5dp"
            android:paddingRight="@dimen/dimen_5dp"
            app:layout_behavior="@string/appbar_scrolling_view_behavior" />

        <com.turacomobile.gb.utils.CustomSFUIMediumTextView
            android:id="@+id/tvSearchMyStreamz"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:padding="8dp"
            android:text="Food from My Streamz Brands"
            android:textColor="@color/black" />

        <android.support.v7.widget.RecyclerView
            android:id="@+id/my_recycler_view"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            app:layout_behavior="@string/appbar_scrolling_view_behavior" />
    </LinearLayout>

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

JAVA

    rvSearchStreamz = findViewById(R.id.my_recycler_view);
    rvMyBrands = findViewById(R.id.rvMyBrands);
    rvRecommendedBrands = findViewById(R.id.rvRecommendedBrands);

    LinearLayoutManager llm = new LinearLayoutManager(this);
    llm.setOrientation(LinearLayoutManager.VERTICAL);
    rvSearchStreamz.setLayoutManager(llm);
    rvSearchStreamz.setNestedScrollingEnabled(false);
    rvSearchStreamz.setHasFixedSize(false);

    LinearLayoutManager llmMy = new LinearLayoutManager(this);
    llmMy.setOrientation(LinearLayoutManager.HORIZONTAL);
    rvMyBrands.setLayoutManager(llmMy);
    rvMyBrands.setNestedScrollingEnabled(false);
    rvMyBrands.setHasFixedSize(false);

    LinearLayoutManager llmRecommended = new LinearLayoutManager(this);
    llmRecommended.setOrientation(LinearLayoutManager.HORIZONTAL);
    rvRecommendedBrands.setLayoutManager(llmRecommended);
    rvRecommendedBrands.setNestedScrollingEnabled(false);
    rvRecommendedBrands.setHasFixedSize(false);

Upvotes: 5

Views: 6754

Answers (3)

VolkanSahin45
VolkanSahin45

Reputation: 1968

The problem is NestedScrollView. You shouldn't use RecyclerView inside a NestedScrollView because RecyclerView don't recycle anything in a NestedScrollView(You can test it with write log in onCreateView and onBindView). Change the container layout type like LinearLayout, RelativeLayout etc.

Upvotes: 5

BarmanInfo
BarmanInfo

Reputation: 392

At first change Adapter initialize

HorizontalAdapterOne hAdapterOne;
HorizontalAdapterTwo hAdapterTwo;

And write this to in your onCreate method in Activity

hAdapterOne=new HorizontalAdapterOne(context,new ArrayList<DemoItemOne>);
hAdaptertwo=new HorizontalAdapterTwo(context,new ArrayList<DemoItemTwo>);

Add a method in your adapter

public void refreshList(ArrayList<DemoModel> demoList){
    if(demoList!=null  && demoList.size()>0){
        this.demoActualList.addAll(demoList);
        notifyDataSetChanged();
    }
}

After getting data from API then call this method from your activity

hAdapterOne.refreshList(demoListFromAPI)

Or You Can use a Custom List View instead of Recycler View for Vertical listing. Check the below list View Class

import android.content.Context;
import android.util.AttributeSet;
import android.view.ViewGroup;
import android.widget.ListView;
public class ExpandableHeightListView extends ListView {
boolean expanded = true;
public ExpandableHeightListView(Context context) {
    super(context);
}
public ExpandableHeightListView(Context context, AttributeSet attrs) {
    super(context, attrs);
}
public ExpandableHeightListView(Context context, AttributeSet attrs,
        int defStyle) {
    super(context, attrs, defStyle);
}
public boolean isExpanded() {
    return expanded;
}
@Override
public void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
    // HACK! TAKE THAT ANDROID!
    if (isExpanded()) {
        // Calculate entire height by providing a very large height hint.
        // View.MEASURED_SIZE_MASK represents the largest height possible.
        int expandSpec = MeasureSpec.makeMeasureSpec(MEASURED_SIZE_MASK,
                MeasureSpec.AT_MOST);
        super.onMeasure(widthMeasureSpec, expandSpec);

        ViewGroup.LayoutParams params = getLayoutParams();
        params.height = getMeasuredHeight();
    } else {
        super.onMeasure(widthMeasureSpec, heightMeasureSpec);
    }
}

public void setExpanded(boolean expanded) {
    this.expanded = expanded;
}
}

Upvotes: 1

Tushar Srivastava
Tushar Srivastava

Reputation: 800

I would recommend you to go with pagination. As far as performance is your concern this can act as a best catalyst.

In pagination we download and set only a specific amount of content into recyclerview.

Blocking of UI thread and be drastically reduced also please go with async task if you have lot of data to render as UI therad is to be maintained as light as possible

below is the link where you can get an idea for the implementation. https://medium.com/@etiennelawlor/pagination-with-recyclerview-1cb7e66a502b

Upvotes: 0

Related Questions