4

I'm using quite complex recyclerView item layout inside recyclerView. I've started to have an issues with performance for quite a while now. Everytime I run app, I get warnings while inflating layouts for views in recyclerView. For example:

D/View: [ANR Warning]onMeasure time too long, this =android.support.constraint.ConstraintLayout{91a57db V.E...... ......I. 0,0-0,0 #7f0801d4 app:id/parentLayout}time =807 ms
D/View: [ANR Warning]onMeasure time too long, this =android.support.constraint.ConstraintLayout{20858c2 V.E...... ......I. 0,0-0,0 #7f0801d4 app:id/parentLayout}time =745 ms
D/View: [ANR Warning]onMeasure time too long, this =android.support.constraint.ConstraintLayout{880b0bc V.E...... ......I. 0,0-0,0 #7f0801d4 app:id/parentLayout}time =705 ms

800ms on average per item is really long time for inflating. I 've measured onBindViewHolder() binding time and its up to 10ms per item which is fine.

Is there any way how to decrease this measure time? I've used only ConstraintLayouts as I find out that constraint is recommended for recyclerView items due to its fast performance.

This item contains expandable layout which will expand on item click.

Item layout:

<android.support.constraint.ConstraintLayout
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/parentLayout"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal">

<android.support.constraint.ConstraintLayout
    android:id="@+id/itemInfo"
    android:layout_width="match_parent"
    android:layout_height="wrap_content">

    <ImageView
        android:id="@+id/imageView"
        android:layout_width="80dp"
        android:layout_height="80dp"
        android:layout_alignParentStart="true"
        android:layout_marginBottom="8dp"
        android:layout_marginStart="16dp"
        android:layout_marginTop="8dp"
        android:visibility="visible"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent"
        app:layout_goneMarginBottom="16dp"
        app:srcCompat="@mipmap/ic_launcher" />

    <android.support.constraint.ConstraintLayout
        android:id="@+id/itemTextLayout"
        android:layout_width="0dp"
        android:layout_height="wrap_content"
        android:layout_marginBottom="16dp"
        android:layout_marginEnd="16dp"
        android:layout_marginStart="16dp"
        android:layout_marginTop="16dp"
        android:visibility="visible"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toEndOf="@+id/imageView"
        app:layout_constraintTop_toTopOf="parent">

        <TextView
            android:id="@+id/itemName"
            android:layout_width="0dp"
            android:layout_height="wrap_content"
            android:layout_gravity="fill"
            android:singleLine="false"
            android:text="itemName"
            android:textColor="@color/colorItemMajor"
            android:textSize="16sp"
            app:layout_constraintEnd_toEndOf="parent"
            app:layout_constraintStart_toStartOf="parent"
            app:layout_constraintTop_toTopOf="parent" />

        <android.support.constraint.ConstraintLayout
            android:id="@+id/BottomLineLayout"
            android:layout_width="0dp"
            android:layout_height="wrap_content"
            android:layout_marginEnd="8dp"
            android:layout_marginTop="4dp"
            android:visibility="visible"
            app:layout_constraintBottom_toBottomOf="parent"
            app:layout_constraintEnd_toStartOf="@+id/itemRate_icon"
            app:layout_constraintStart_toStartOf="parent"
            app:layout_constraintTop_toBottomOf="@id/itemName">

            <ImageView
                android:id="@+id/itemStatus"
                android:layout_width="wrap_content"
                android:layout_height="12dp"
                android:layout_marginEnd="4dp"
                app:layout_constraintBottom_toBottomOf="parent"
                app:layout_constraintEnd_toStartOf="@+id/itemSupplier"
                app:layout_constraintStart_toStartOf="parent"
                app:layout_constraintTop_toTopOf="parent" />

            <TextView
                android:id="@+id/itemSupplier"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_gravity="fill"
                android:layout_marginEnd="4dp"
                android:text="suppName"
                android:textColor="@color/colorItemMinor"
                android:textSize="10sp"
                app:layout_constraintBottom_toBottomOf="parent"
                app:layout_constraintEnd_toStartOf="@+id/itemDel_icon"
                app:layout_constraintStart_toEndOf="@id/itemStatus"
                app:layout_constraintTop_toTopOf="parent" />

            <ImageView
                android:id="@+id/itemDel_icon"
                android:layout_width="12dp"
                android:layout_height="12dp"
                android:layout_marginEnd="4dp"
                app:layout_constraintBottom_toBottomOf="parent"
                app:layout_constraintEnd_toStartOf="@+id/itemDel"
                app:layout_constraintStart_toEndOf="@id/itemSupplier"
                app:layout_constraintTop_toTopOf="parent"
                app:srcCompat="@mipmap/ic_launcher" />

            <TextView
                android:id="@+id/itemDel"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_gravity="fill"
                android:layout_marginEnd="4dp"
                android:text="itemDel"
                android:textColor="@color/colorItemMinor"
                android:textSize="10sp"
                app:layout_constraintBottom_toBottomOf="parent"
                app:layout_constraintEnd_toStartOf="@+id/itemWT_icon"
                app:layout_constraintStart_toEndOf="@+id/itemDel_icon"
                app:layout_constraintTop_toTopOf="parent" />

            <ImageView
                android:id="@+id/itemWT_icon"
                android:layout_width="12dp"
                android:layout_height="12dp"
                android:layout_marginStart="4dp"
                app:layout_constraintBottom_toBottomOf="parent"
                app:layout_constraintStart_toEndOf="@id/itemDel"
                app:layout_constraintTop_toTopOf="parent"
                app:srcCompat="@mipmap/ic_launcher" />

            <TextView
                android:id="@+id/itemWT"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_alignBaseline="@+id/itemWT_icon"
                android:layout_alignBottom="@+id/itemWT_icon"
                android:layout_gravity="fill"
                android:layout_marginStart="4dp"
                android:layout_toEndOf="@+id/itemWT_icon"
                android:text="itemWT"
                android:textColor="@color/colorItemMinor"
                android:textSize="10sp"
                app:layout_constraintBottom_toBottomOf="parent"
                app:layout_constraintStart_toEndOf="@+id/itemWT_icon"
                app:layout_constraintTop_toTopOf="parent" />
        </android.support.constraint.ConstraintLayout>

        <ImageView
            android:id="@+id/itemRate_icon"
            android:layout_width="12dp"
            android:layout_height="12dp"
            android:layout_marginEnd="4dp"
            android:layout_marginTop="4dp"
            app:layout_constraintEnd_toStartOf="@id/itemRate"
            app:layout_constraintTop_toBottomOf="@+id/itemName"
            app:srcCompat="@mipmap/ic_launcher" />

        <TextView
            android:id="@+id/itemRate"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_alignBaseline="@+id/itemRate_icon"
            android:layout_alignBottom="@+id/itemRate_icon"
            android:layout_gravity="fill"
            android:layout_marginTop="4dp"
            android:text="itemRate"
            android:textColor="@color/colorRating"
            android:textSize="10sp"
            android:textStyle="bold"
            app:layout_constraintEnd_toEndOf="parent"
            app:layout_constraintTop_toBottomOf="@+id/itemName" />

    </android.support.constraint.ConstraintLayout>

</android.support.constraint.ConstraintLayout>

<android.support.constraint.ConstraintLayout
    android:id="@+id/expandable_layout"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:animateLayoutChanges="true"
    android:background="@color/colorBackground"
    android:orientation="horizontal"
    android:visibility="visible"
    app:layout_constraintTop_toBottomOf="@+id/itemInfo">

    <ImageView
        android:id="@+id/arrowPointer"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        app:srcCompat="@mipmap/ic_launcher"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent" />

    <TextView
        android:id="@+id/itemDesc"
        android:layout_width="0dp"
        android:layout_height="wrap_content"
        android:layout_gravity="fill"
        android:layout_marginEnd="32dp"
        android:layout_marginStart="16dp"
        android:layout_marginTop="24dp"
        android:singleLine="false"
        android:text="This is some item desc."
        android:textColor="@color/colorItemMinor"
        android:textSize="12sp"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent" />

    <ImageView
        android:id="@+id/itemWeight_icon"
        android:layout_width="12sp"
        android:layout_height="12sp"
        android:layout_marginStart="16dp"
        android:layout_marginTop="20dp"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toBottomOf="@id/itemDesc"
        app:srcCompat="@mipmap/ic_launcher" />

    <TextView
        android:id="@+id/itemWeight"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_alignBaseline="@+id/itemWeight_icon"
        android:layout_alignBottom="@+id/itemWeight_icon"
        android:layout_gravity="fill"
        android:layout_marginStart="4dp"
        android:layout_marginTop="20dp"
        android:layout_toEndOf="@+id/itemWeight_icon"
        android:text="itemWeight"
        android:textColor="@color/colorItemMinor"
        android:textSize="10sp"
        app:layout_constraintStart_toEndOf="@+id/itemWeight_icon"
        app:layout_constraintTop_toBottomOf="@+id/itemDesc" />

    <ImageView
        android:id="@+id/itemType_icon"
        android:layout_width="12sp"
        android:layout_height="12sp"
        android:layout_marginStart="8dp"
        android:layout_marginTop="20dp"
        app:layout_constraintStart_toEndOf="@id/itemWeight"
        app:layout_constraintTop_toBottomOf="@id/itemDesc"
        app:srcCompat="@mipmap/ic_launcher" />

    <TextView
        android:id="@+id/itemType"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_alignBaseline="@+id/itemType_icon"
        android:layout_alignBottom="@+id/itemType_icon"
        android:layout_gravity="fill"
        android:layout_marginStart="4dp"
        android:layout_marginTop="20dp"
        android:layout_toEndOf="@+id/itemType_icon"
        android:text="itemType"
        android:textColor="@color/colorItemMinor"
        android:textSize="10sp"
        app:layout_constraintStart_toEndOf="@+id/itemType_icon"
        app:layout_constraintTop_toBottomOf="@+id/itemDesc" />

    <android.support.constraint.ConstraintLayout
        android:id="@+id/propertyRow"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_marginTop="4dp"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toBottomOf="@id/itemType_icon">

        <TextView
            android:id="@+id/propertyChangeClickableText"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_gravity="fill"
            android:layout_marginStart="16dp"
            android:clickable="true"
            android:focusable="true"
            android:text="Change Properties"
            android:textColor="@color/colorPrice"
            android:textSize="16sp"
            app:layout_constraintBottom_toBottomOf="parent"
            app:layout_constraintStart_toStartOf="parent"
            app:layout_constraintTop_toTopOf="parent" />

        <ImageButton
            android:id="@+id/confirmItemButton"
            android:layout_width="56dp"
            android:layout_height="56dp"
            android:layout_marginEnd="16dp"
            android:background="@drawable/image_button_border_drawable"
            android:scaleType="fitCenter"
            app:srcCompat="@mipmap/ic_launcher"
            app:layout_constraintBottom_toBottomOf="parent"
            app:layout_constraintEnd_toEndOf="parent"
            app:layout_constraintTop_toTopOf="parent" />
    </android.support.constraint.ConstraintLayout>

    <View
        android:id="@+id/separator"
        android:layout_width="match_parent"
        android:layout_height="1dp"
        android:layout_marginTop="16dp"
        android:background="@color/colorDivider"
        app:layout_constraintTop_toBottomOf="@id/propertyRow" />

    <android.support.constraint.ConstraintLayout
        android:id="@+id/topRowLayoutPopup"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_marginTop="8dp"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toBottomOf="@id/separator">

        <TextView
            android:id="@+id/itemSupplierName"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_gravity="fill"
            android:layout_marginStart="16dp"
            android:text="supName"
            android:textColor="@color/colorItemMajor"
            android:textSize="16sp"
            app:layout_constraintBottom_toBottomOf="parent"
            app:layout_constraintStart_toStartOf="parent"
            app:layout_constraintTop_toTopOf="parent" />

        <ImageView
            android:id="@+id/property1_ico"
            android:layout_width="16dp"
            android:layout_height="16dp"
            android:layout_alignBaseline="@+id/itemSupplierName"
            android:layout_marginEnd="4dp"
            app:layout_constraintBottom_toBottomOf="parent"
            app:layout_constraintEnd_toStartOf="@id/property2_ico"
            app:layout_constraintTop_toTopOf="parent"
            app:srcCompat="@mipmap/ic_launcher" />

        <ImageView
            android:id="@+id/property2_ico"
            android:layout_width="16dp"
            android:layout_height="16dp"
            android:layout_alignBaseline="@+id/itemSupplierName"
            android:layout_marginEnd="4dp"
            app:layout_constraintBottom_toBottomOf="parent"
            app:layout_constraintEnd_toStartOf="@id/property3_ico"
            app:layout_constraintTop_toTopOf="parent"
            app:srcCompat="@mipmap/ic_launcher" />

        <ImageView
            android:id="@+id/property3_ico"
            android:layout_width="16dp"
            android:layout_height="16dp"
            android:layout_alignBaseline="@+id/itemSupplierName"
            android:layout_marginEnd="16dp"
            app:layout_constraintBottom_toBottomOf="parent"
            app:layout_constraintEnd_toEndOf="parent"
            app:layout_constraintTop_toTopOf="parent"
            app:srcCompat="@mipmap/ic_launcher" />
    </android.support.constraint.ConstraintLayout>

    <android.support.constraint.ConstraintLayout
        android:id="@+id/bottomRowLayoutPopup"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_marginBottom="24dp"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toBottomOf="@id/topRowLayoutPopup">

        <TextView
            android:id="@+id/editSupplierButton"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_alignBaseline="@+id/supplierRatingBar"
            android:layout_marginStart="16dp"
            android:clickable="true"
            android:focusable="true"
            android:text="Edit Supplier"
            android:textColor="@color/colorPrice"
            android:textSize="16sp"
            app:layout_constraintBottom_toBottomOf="parent"
            app:layout_constraintStart_toStartOf="parent"
            app:layout_constraintTop_toTopOf="parent" />

        <TextView
            android:id="@+id/supplierRating"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_alignBaseline="@+id/supplierRatingBar"
            android:layout_gravity="fill"
            android:layout_marginEnd="8dp"
            android:text="supplierRating"
            android:textColor="@color/colorRating"
            android:textSize="@dimen/food_list_bottom_row_font"
            android:textStyle="bold"
            app:layout_constraintBottom_toBottomOf="parent"
            app:layout_constraintEnd_toStartOf="@id/supplierRatingBar"
            app:layout_constraintTop_toTopOf="parent" />

        <RatingBar
            android:id="@+id/supplierRatingBar"
            style="@style/RatingBarStyle"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_marginEnd="8dp"
            app:layout_constraintBottom_toBottomOf="parent"
            app:layout_constraintEnd_toStartOf="@+id/supplierRatingRateNumber"
            app:layout_constraintTop_toTopOf="parent" />

        <TextView
            android:id="@+id/supplierRatingRateNumber"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_alignBaseline="@+id/supplierRatingBar"
            android:layout_gravity="fill"
            android:layout_marginEnd="16dp"
            android:text="RateNum"
            android:textColor="@color/colorItemMinor"
            android:textSize="10sp"
            app:layout_constraintBottom_toBottomOf="parent"
            app:layout_constraintEnd_toEndOf="parent"
            app:layout_constraintTop_toTopOf="parent" />
    </android.support.constraint.ConstraintLayout>

</android.support.constraint.ConstraintLayout>

12
  • Are you using any api or making network calls in main thread that may affect the performance? Commented Sep 10, 2018 at 11:20
  • I'm using Glide API to load image from URL to main ImageView. Commented Sep 10, 2018 at 11:22
  • Check the size of the images! You may want to compress it. Commented Sep 10, 2018 at 11:23
  • Size of each image is 240x240 (if you meant resolution) Commented Sep 10, 2018 at 11:27
  • 2
    Too many nested ConstraintLayouts! You need to put all the views under one ConstraintLayout at the top. This way you can still use animations and you won't have a layout perf problem. Commented Sep 11, 2018 at 9:26

2 Answers 2

7

So as @RamiJemli suggested I replaced all of my ConstraintLayouts with RelativeLayouts and performance is awesome. Zero skipped frames - clear 60fps app run. Clearly those articles about ConstraintLayout > RelativeLayout in RecyclerViews are not that true (at least in my app).

Sign up to request clarification or add additional context in comments.

4 Comments

I have been using ConstrainLayout everywhere but today I just saw this log got stuck for hours with this ANR issue, replacing it with RelativeLayout worked like a charm. The unsung pitfall of ConstrainLayout that no one will tell you.
Tried many things before this, to reduce janky frames into the recycler view, but this trick made wonders.
In some cases, the recyclerView could be the major cause of this, if in your layout, you have a view that expands, and you have layout_height of your recycler as match_parent, the recyclerView adapter will bind all the items at once instead of handling them in bits as it's supposed to. Check this answer for more detail stackoverflow.com/a/71323597/7478839.
This is so weird that everywhere on the internet(even Google) they have crowned ConstraintLayout as the king of all layouts but clearly it does not come close when it comes to performance.
0

I've faced a problem like this, so, instead of using a constraints layout, I've used a relative layout and it worked very well. Actually, I am surprised, I thought that constraints layout is a better version of relative layout but in my case, relative layout performed much better.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.