so I tried refactoring some of my recycler ViewHolders
to ConstraintLayouts
. After I did it I was shocked after what I saw. Inflating a single view takes 20x more time than usual LinearLayout
. It actually skips so many frames while doing it.
EDIT: Version of constraint layout is not relevant. Tried different combinations had almost the same results.
Can any one explain why is this happening? Maybe it's not designed for such "heavy" views?
Here is a root XML
that is used in ViewHolder
:
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="@color/white"
android:elevation="@dimen/param_2"
android:orientation="vertical"
android:stateListAnimator="@animator/material_selector">
<LinearLayout
android:id="@+id/order_view_tabs_container"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginBottom="@dimen/param_2"
android:padding="@dimen/param_4"
android:background="@color/white"
android:divider="@drawable/empty_horizontal_divider"
android:elevation="@dimen/param_2"
android:orientation="horizontal"
android:showDividers="middle"
android:visibility="gone"/>
<include layout="@layout/order_list_item_constraint"/>
</LinearLayout>
And here is order_list_item_constraint.xml
<android.support.constraint.ConstraintLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:padding="@dimen/param_4"
android:clipToPadding="false">
<TextView
android:id="@+id/delivery_status"
style="@style/DefaultText.Normal"
android:layout_width="0dp"
android:layout_height="50dp"
android:layout_marginEnd="4dp"
android:padding="4dp"
android:background="@color/white"
android:elevation="2dp"
android:gravity="center_vertical"
android:text="@string/main_swipe_list_item_info_title_delivered_time"
app:layout_constraintEnd_toStartOf="@id/mid_guideline"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
tools:layout_editor_absoluteY="4dp"/>
<TextView
android:id="@+id/order_list_item_order_title"
style="@style/FullListItemInfoText"
android:layout_width="0dp"
android:layout_marginTop="4dp"
android:text="@string/main_swipe_list_item_info_title_order"
android:textColor="@color/red_900"
app:layout_constraintEnd_toEndOf="@id/mid_guideline"
app:layout_constraintStart_toStartOf="@id/start_guideline"
app:layout_constraintTop_toBottomOf="@+id/delivery_status"/>
<TextView
android:id="@+id/order_list_item_order_id"
style="@style/FullListItemInfoDetailsText"
android:layout_width="0dp"
app:layout_constraintEnd_toEndOf="@id/mid_guideline"
app:layout_constraintStart_toStartOf="@+id/start_guideline"
app:layout_constraintTop_toBottomOf="@id/order_list_item_order_title"
/>
<TextView
android:id="@+id/order_list_item_price_title"
style="@style/FullListItemInfoText"
android:layout_width="0dp"
android:layout_marginTop="4dp"
android:text="@string/main_swipe_list_item_info_title_sum"
app:layout_constraintEnd_toEndOf="@id/mid_guideline"
app:layout_constraintStart_toStartOf="@id/start_guideline"
app:layout_constraintTop_toBottomOf="@+id/order_list_item_order_id"
/>
<TextView
android:id="@+id/order_list_item_price"
style="@style/FullListItemInfoDetailsText"
android:layout_width="0dp"
app:layout_constraintEnd_toEndOf="@id/mid_guideline"
app:layout_constraintStart_toStartOf="@+id/start_guideline"
app:layout_constraintTop_toBottomOf="@id/order_list_item_price_title"
/>
<TextView
android:id="@+id/order_list_item_threshold_title"
style="@style/FullListItemInfoText"
android:layout_width="0dp"
android:layout_marginTop="4dp"
android:text="@string/order_full_list_item_threshold_value_title"
app:layout_constraintEnd_toEndOf="@id/mid_guideline"
app:layout_constraintStart_toStartOf="@id/start_guideline"
app:layout_constraintTop_toBottomOf="@+id/order_list_item_price"
/>
<TextView
android:id="@+id/order_list_item_threshold_value"
style="@style/FullListItemInfoDetailsText"
android:layout_width="0dp"
app:layout_constraintEnd_toEndOf="@id/mid_guideline"
app:layout_constraintStart_toStartOf="@+id/start_guideline"
app:layout_constraintTop_toBottomOf="@id/order_list_item_threshold_title"
/>
<TextView
android:id="@+id/order_list_item_sl_title"
style="@style/FullListItemInfoText"
android:layout_width="0dp"
android:layout_marginTop="@dimen/param_4"
android:text="@string/main_swipe_list_item_info_title_service_level"
app:layout_constraintEnd_toEndOf="@id/mid_guideline"
app:layout_constraintStart_toStartOf="@id/start_guideline"
app:layout_constraintTop_toBottomOf="@+id/order_list_item_threshold_value"/>
<TextView
android:id="@+id/order_list_item_service_level_title"
style="@style/FullListItemInfoDetailsText"
android:textStyle="bold"
android:layout_width="0dp"
android:textSize="@dimen/text_size_12"
app:layout_constraintEnd_toEndOf="@id/mid_guideline"
app:layout_constraintStart_toStartOf="@id/start_guideline"
app:layout_constraintTop_toBottomOf="@+id/order_list_item_sl_title"/>
<TextView
android:id="@+id/order_list_item_service_level_try_on"
style="@style/FullListItemInfoDetailsText"
android:layout_width="0dp"
android:textSize="@dimen/text_size_12"
app:layout_constraintEnd_toEndOf="@id/mid_guideline"
app:layout_constraintStart_toStartOf="@id/start_guideline"
app:layout_constraintTop_toBottomOf="@+id/order_list_item_service_level_title"/>
<TextView
android:id="@+id/order_list_item_service_level_partial_purchase"
style="@style/FullListItemInfoDetailsText"
android:layout_width="0dp"
android:textSize="@dimen/text_size_12"
app:layout_constraintEnd_toEndOf="@id/mid_guideline"
app:layout_constraintStart_toStartOf="@id/start_guideline"
app:layout_constraintTop_toBottomOf="@+id/order_list_item_service_level_try_on"/>
<com.express.mobile.customView.MyNetworkImageView
android:id="@+id/order_list_item_image_map"
android:layout_width="0dp"
android:layout_height="144dp"
android:elevation="2dp"
android:scaleType="centerCrop"
android:visibility="visible"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="@id/mid_guideline"
app:layout_constraintTop_toTopOf="parent"/>
<ImageView
android:id="@+id/order_list_item_map_pin"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:paddingBottom="@dimen/param_30"
android:contentDescription="@null"
android:elevation="2dp"
android:src="@drawable/ic_map_pin_sz_1"
android:visibility="gone"
app:layout_constrainedHeight="true"
app:layout_constrainedWidth="true"
app:layout_constraintBottom_toBottomOf="@id/order_list_item_image_map"
app:layout_constraintEnd_toEndOf="@id/order_list_item_image_map"
app:layout_constraintStart_toStartOf="@id/order_list_item_image_map"
app:layout_constraintTop_toTopOf="@id/order_list_item_image_map"/>
<include
android:id="@+id/order_list_item_map_interval_box"
layout="@layout/map_interval_box"
android:layout_width="wrap_content"
android:layout_height="@dimen/param_48"
app:layout_constrainedWidth="true"
app:layout_constraintStart_toStartOf="@id/order_list_item_image_map"/>
<TextView
android:id="@+id/order_list_item_timer"
style="@style/WhiteText.Large"
android:textStyle="bold"
android:layout_width="0dp"
android:layout_height="0dp"
android:background="@drawable/order_full_list_item_delivery_status_box_borders"
android:elevation="2dp"
android:gravity="center"
android:text="@string/timer_zero_time_value_text"
android:textSize="@dimen/text_size_24"
android:visibility="gone"
app:layout_constraintBottom_toBottomOf="@id/order_list_item_map_interval_box"
app:layout_constraintEnd_toEndOf="@id/order_list_item_map_interval_box"
app:layout_constraintStart_toStartOf="@id/order_list_item_map_interval_box"
app:layout_constraintTop_toTopOf="@id/order_list_item_map_interval_box"/>
<ImageView
android:id="@+id/order_list_item_partner_icon"
android:layout_width="@dimen/param_40"
android:layout_height="@dimen/param_40"
android:layout_margin="4dp"
android:background="@drawable/order_mod_icon"
android:backgroundTint="@color/red_800"
android:contentDescription="@null"
android:elevation="@dimen/param_4"
android:scaleType="center"
android:src="@drawable/ic_partner"
android:visibility="gone"
app:layout_constraintBottom_toBottomOf="@+id/order_list_item_image_map"
app:layout_constraintStart_toStartOf="@+id/order_list_item_image_map"/>
<ImageView
android:id="@+id/order_list_item_prepaid_icon"
android:layout_width="@dimen/param_40"
android:layout_height="@dimen/param_40"
android:layout_margin="4dp"
android:background="@drawable/order_mod_icon"
android:backgroundTint="@color/green_800"
android:contentDescription="@null"
android:elevation="@dimen/param_4"
android:scaleType="center"
android:src="@drawable/ic_prepaid"
android:visibility="gone"
app:layout_constraintBottom_toBottomOf="@+id/order_list_item_image_map"
app:layout_constraintStart_toEndOf="@id/order_list_item_partner_icon"/>
<ImageView
android:id="@+id/order_list_item_microcredit_icon"
android:layout_width="@dimen/param_40"
android:layout_height="@dimen/param_40"
android:layout_margin="4dp"
android:background="@drawable/order_mod_icon"
android:backgroundTint="@color/blue_grey_700"
android:contentDescription="@null"
android:elevation="@dimen/param_4"
android:scaleType="center"
android:src="@drawable/ic_microcredit"
android:visibility="gone"
app:layout_constraintBottom_toBottomOf="@+id/order_list_item_image_map"
app:layout_constraintStart_toEndOf="@id/order_list_item_prepaid_icon"/>
<ImageView
android:id="@+id/order_list_item_ongoing_icon"
android:layout_width="@dimen/param_40"
android:layout_height="@dimen/param_40"
android:layout_margin="4dp"
android:background="@drawable/order_mod_icon"
android:backgroundTint="@color/colorPrimaryDark"
android:contentDescription="@null"
android:elevation="@dimen/param_4"
android:scaleType="center"
android:src="@drawable/ic_delivery_time_ongoing"
android:visibility="gone"
app:layout_constraintBottom_toBottomOf="@+id/order_list_item_image_map"
app:layout_constraintStart_toEndOf="@id/order_list_item_microcredit_icon"/>
<TextView
android:id="@+id/order_list_item_name"
style="@style/FullListItemInfoDetailsText"
android:layout_width="0dp"
android:layout_height="@dimen/param_20"
android:layout_marginTop="8dp"
android:drawablePadding="@dimen/param_8"
android:drawableStart="@drawable/ic_man"
android:maxLines="1"
app:layout_constraintEnd_toStartOf="@id/order_list_item_call_icon"
app:layout_constraintStart_toStartOf="@id/mid_guideline"
app:layout_constraintTop_toBottomOf="@id/order_list_item_image_map"/>
<TextView
android:id="@+id/order_list_item_phone"
style="@style/FullListItemInfoDetailsText"
android:layout_width="0dp"
android:layout_height="@dimen/param_20"
android:layout_marginStart="@dimen/param_28"
android:maxLines="1"
app:layout_constraintEnd_toStartOf="@id/order_list_item_call_icon"
app:layout_constraintStart_toStartOf="@id/mid_guideline"
app:layout_constraintTop_toBottomOf="@id/order_list_item_name"/>
<ImageView
android:id="@+id/address_icon"
android:layout_width="@dimen/param_20"
android:layout_height="@dimen/param_20"
android:layout_marginTop="4dp"
android:contentDescription="@null"
android:src="@drawable/ic_address"
app:layout_constraintStart_toStartOf="@id/mid_guideline"
app:layout_constraintTop_toBottomOf="@id/order_list_item_phone"/>
<TextView
android:id="@+id/order_list_item_address"
style="@style/FullListItemInfoDetailsText"
android:layout_width="0dp"
android:layout_weight="1"
android:layout_marginTop="4dp"
android:layout_marginStart="8dp"
android:layout_marginEnd="4dp"
android:minLines="2"
app:layout_constraintEnd_toStartOf="@id/order_list_item_call_icon"
app:layout_constraintStart_toEndOf="@id/address_icon"
app:layout_constraintTop_toBottomOf="@id/order_list_item_phone"/>
<ImageView
android:id="@+id/order_list_item_call_icon"
android:layout_width="38dp"
android:layout_height="38dp"
android:padding="@dimen/param_8"
android:background="@drawable/order_mod_icon"
android:contentDescription="@null"
android:elevation="@dimen/param_4"
android:src="@drawable/ic_call"
android:visibility="visible"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toTopOf="@id/order_list_item_name"/>
<ImageView
android:id="@+id/order_list_item_navigate_icon"
android:layout_width="38dp"
android:layout_height="38dp"
android:padding="@dimen/param_8"
android:background="@drawable/order_mod_icon"
android:contentDescription="@null"
android:elevation="@dimen/param_4"
android:src="@drawable/ic_order_navigate"
android:visibility="visible"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toTopOf="@id/order_list_item_address"/>
<android.support.constraint.Guideline
android:id="@+id/mid_guideline"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="vertical"
app:layout_constraintGuide_end="360dp"/>
<android.support.constraint.Guideline
android:id="@+id/start_guideline"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="vertical"
app:layout_constraintGuide_begin="4dp"
app:layout_constraintStart_toStartOf="parent"/>
</android.support.constraint.ConstraintLayout>
Here is proof of problem. All child views have measure times around 0.1ms
Comparing a simple LinearLayout
EDIT2: Here is a layout version with LinearLayout's: https://pastebin.com/ZvffUHnw
Results show that the fastest layout is Relative Layout, but difference between this and Linear Layout is really small, what we can't say about Constraint Layout. More complex layout but results are the same, flat Constraint Layout is slower than nested Linear Layout.
ConstraintLayout has flat view hierarchy unlike other layouts, so does a better performance than relative layout. Yes, this is the biggest advantage of Constraint Layout, the only single layout can handle your UI.
Most of what can be achieved in LinearLayout and RelativeLayout can be done in ConstraintLayout.
A ConstraintLayout is a ViewGroup which allows you to position and size widgets in a flexible way. Note: ConstraintLayout is available as a support library that you can use on Android systems starting with API level 9 (Gingerbread).
That's definitely not expected -- I'll have to investigate more to see what's causing it. Note that 1.1 beta is right now going to be slower than 1.0, all the optimizer passes aren't enabled. At first glance there's a lot of textview with 0dp width, which is pretty costly -- like with linear layout, 0dp is going to result in a double measure. E.g. instead of:
<TextView
android:id="@+id/order_list_item_order_title"
android:layout_width="0dp"
android:layout_height="20dp"
android:layout_marginTop="4dp"
android:text="@string/main_swipe_list_item_info_title_order"
app:layout_constraintEnd_toEndOf="@id/mid_guideline"
app:layout_constraintStart_toStartOf="@id/start_guideline"
app:layout_constraintTop_toBottomOf="@+id/delivery_status"/>
You could do:
<TextView
android:id="@+id/order_list_item_order_title"
android:layout_width="wrap_content"
android:layout_height="20dp"
android:layout_marginTop="4dp"
android:text="@string/main_swipe_list_item_info_title_order"
app:layout_constraintStart_toStartOf="@id/start_guideline"
app:layout_constraintTop_toBottomOf="@+id/delivery_status"/>
You don't need to have both a start and end constraints here as well, as you are using guidelines.
Note that in general, HierarchyViewer isn't going to be giving you accurate measurements (that said with such a difference, something seems wrong there).
How does your com.express.mobile.customView.MyNetworkImageView custom view handles measures? as you set it to 0dp it will also be double-measured in your layout.
Finally, Could you add what's in your included layout order_list_item_map_interval_box ?
edit 1.1 beta 6 should improve performances quite a log
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With