在Android中优化慢速自定义视图

时间:2018-03-11 19:33:54

标签: android performance android-custom-view layout-inflater

我有自定义视图。它需要多次创建并添加到一些列表布局中。

for (final Coupon coupon : sessionCoupons) {
       final StatusCouponView couponView = new StatusCouponView(getContext());
       ...
       couponsListLayout.addView(couponView);
}

每个实例的创建大约需要50毫秒,这很慢。大部分时间都由View.inflate方法使用。如何优化它?

public class StatusCouponView extends FrameLayout {
        public StatusCouponView(@NonNull Context context) {
            super(context);
            initView();
        }

        private void initView() {
            this.listener = null;
            addView(View.inflate(getContext(), R.layout.view_status_coupon, null));
            initViews();
        }

        private void initViews() {
            couponLayoutFront = (LinearLayout) findViewById(R.id.view_status_coupon_layout_front);
            couponLayoutBack = (LinearLayout) findViewById(R.id.view_status_coupon_layout_back);
            ...
            couponInfo = (ImageView) findViewById(R.id.view_status_coupon_add_icon);
        }
}

更新:这是布局。它有背面的LinearLayouts和优惠券的正面(在代码中翻转)。

<?xml version="1.0" encoding="utf-8"?>
<FrameLayout 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">

    <LinearLayout
        android:id="@+id/view_status_coupon_layout_back"
        android:layout_width="match_parent"
        android:layout_height="@dimen/main_view_status_coupon_height"
        android:layout_marginTop="@dimen/main_view_status_item_top_margin"
        android:orientation="vertical">

        <RelativeLayout
            android:layout_width="match_parent"
            android:layout_height="match_parent">

            <ScrollView
                android:id="@+id/view_status_coupon_details_scroll"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:layout_marginBottom="30dp"
                android:layout_marginTop="10dp"
                android:fadingEdgeLength="20dp"
                android:requiresFadingEdge="vertical"
                android:scrollbars="none">

                <com.appcard.androidterminal.ui.content_view.styleable_view.StyleableTextView
                    android:id="@+id/view_status_coupon_details"
                    android:layout_width="match_parent"
                    android:layout_height="wrap_content"
                    android:layout_marginEnd="30dp"
                    android:layout_marginStart="30dp"
                    android:gravity="center"
                    android:padding="@dimen/main_view_status_coupon_padding"
                    android:scrollbars="none"
                    android:textAlignment="center"
                    android:textSize="18sp" />
            </ScrollView>

            <ImageView
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_alignParentBottom="true"
                android:layout_marginBottom="7dp"
                android:layout_marginStart="12dp"
                android:padding="5dp"
                android:src="@drawable/ic_coupon_info_close" />

        </RelativeLayout>

    </LinearLayout>

    <LinearLayout
        android:id="@+id/view_status_coupon_layout_front"
        android:layout_width="match_parent"
        android:layout_height="@dimen/main_view_status_coupon_height"
        android:layout_marginTop="@dimen/main_view_status_item_top_margin">

        <RelativeLayout
            android:layout_width="wrap_content"
            android:layout_height="match_parent">

            <ImageView
                android:id="@+id/view_status_coupon_image"
                android:layout_width="@dimen/main_view_status_coupon_image_size"
                android:layout_height="@dimen/main_view_status_coupon_image_size"
                android:layout_centerInParent="true"
                android:layout_gravity="center_vertical"
                android:layout_marginBottom="@dimen/main_view_status_coupon_image_margin_vertical"
                android:layout_marginEnd="@dimen/main_view_status_coupon_image_margin_horizontal"
                android:layout_marginStart="@dimen/main_view_status_coupon_image_margin_horizontal"
                android:layout_marginTop="@dimen/main_view_status_coupon_image_margin_vertical"
                tools:src="@android:mipmap/sym_def_app_icon" />

            <ImageView
                android:id="@+id/view_status_coupon_info"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_alignParentBottom="true"
                android:layout_marginBottom="7dp"
                android:layout_marginStart="12dp"
                android:padding="5dp"
                android:src="@drawable/ic_coupon_info" />

        </RelativeLayout>

        <RelativeLayout
            android:layout_width="0dp"
            android:layout_height="match_parent"
            android:layout_marginBottom="@dimen/main_view_status_coupon_padding"
            android:layout_marginEnd="5dp"
            android:layout_marginTop="@dimen/main_view_status_coupon_padding"
            android:layout_weight="1">

            <com.appcard.androidterminal.ui.content_view.styleable_view.StyleableTextView
                android:id="@+id/view_status_coupon_title"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_alignParentTop="true"
                android:layout_marginBottom="10dp"
                android:ellipsize="end"
                android:gravity="center_vertical"
                android:lineSpacingMultiplier="0.88"
                android:singleLine="true"
                android:textSize="@dimen/main_small_text_size"
                tools:text="Save $1.00" />

            <com.appcard.androidterminal.ui.content_view.styleable_view.StyleableTextView
                android:id="@+id/view_status_coupon_name"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_below="@+id/view_status_coupon_title"
                android:layout_marginBottom="10dp"
                android:ellipsize="end"
                android:gravity="center_vertical"
                android:lineSpacingMultiplier="0.88"
                android:singleLine="true"
                android:textSize="@dimen/main_x_x_x_x_x_small_text_size"
                app:styleable_font="bold"
                tools:text="Honey Nut Cheerios" />

            <com.appcard.androidterminal.ui.content_view.styleable_view.StyleableTextView
                android:id="@+id/view_status_coupon_desc"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_below="@id/view_status_coupon_name"
                android:ellipsize="end"
                android:gravity="center_vertical"
                android:maxLines="3"
                android:textSize="18sp"
                tools:text="on any ONE (1) Windex® Product (excludes travel and trial sizes)" />

            <com.appcard.androidterminal.ui.content_view.styleable_view.StyleableTextView
                android:id="@+id/view_status_coupon_expire_date"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_alignParentBottom="true"
                android:ellipsize="end"
                android:gravity="center_vertical"
                android:lineSpacingMultiplier="0.88"
                android:singleLine="true"
                android:textSize="18sp"
                tools:text="Expires April 20, 2018" />

        </RelativeLayout>

        <RelativeLayout
            android:id="@+id/view_status_coupon_add_layout"
            android:layout_width="@dimen/main_view_status_item_value_width"
            android:layout_height="match_parent"
            android:background="@drawable/bg_card_value"
            android:orientation="vertical">

            <LinearLayout
                android:layout_width="match_parent"
                android:layout_height="match_parent"
                android:layout_centerInParent="true"
                android:gravity="center"
                android:orientation="vertical">

                <ImageView
                    android:id="@+id/view_status_coupon_add_icon"
                    android:layout_width="96dp"
                    android:layout_height="96dp"
                    android:src="@drawable/ic_add_coupon" />

                <com.appcard.androidterminal.ui.content_view.styleable_view.StyleableTextView
                    android:layout_width="wrap_content"
                    android:layout_height="wrap_content"
                    android:text="Add"
                    android:textSize="@dimen/main_x_x_small_text_size"
                    app:styleable_color="white"
                    app:styleable_font="bold" />
            </LinearLayout>

            <ImageView
                android:id="@+id/view_status_coupon_info_close"
                android:layout_width="35dp"
                android:layout_height="35dp"
                android:layout_alignParentBottom="true"
                android:layout_alignParentEnd="true"
                android:layout_marginBottom="7dp"
                android:layout_marginEnd="12dp"
                android:padding="5dp" />

        </RelativeLayout>
    </LinearLayout>

</FrameLayout>

1 个答案:

答案 0 :(得分:1)

避免通过您在代码段中提到的循环在运行时手动将视图添加到布局中。

如果你有很多对象(比你可以在屏幕上显示的更多),你最好使用处理回收视图的ViewGroup,以避免创建不必要的视图。你最好的选择是RecyclerView

如果您查看真的很费用,可以使用RecyclerView ConstraintLayout

RelativeLayout的一些设施进行优化

然而,这并不是真正解决您的实际问题,您需要更快地进行自定义视图,您应该将层次结构扁平化以使通胀过程更快,一个非常好的候选者就是使用49, 32, 30[49, 32, 30]如果它可以帮助您删除嵌套布局。