android - 为什么膨胀一个 Android 布局需要这么长时间?

标签 android performance android-layout

我在 Android 中有一个对话框。打开时有明显的延迟。这是我所做的调查:

  • 使用 System.currentTime 的粗略计时,我的 onCreateDialog 方法在正常的一天需要 500-700 毫秒的好日子需要 150 毫秒。
  • 我实现了自己的 LayoutInflator.Factory。我的工厂什么都不做。它只是返回 null 以让默认工厂完成工作。然而,它会写出自上次调用以来耗时。这样,我可以打印出布局 xml 中的每个标签需要多长时间才能膨胀。非常令人惊讶的是,每个元素充气大约需要 20-70 毫秒!
  • 我分析了该应用程序。看来很多时间确实花在了 View 的构造函数或 LayoutParams 上。
  • 对于粗略的检查,我测量了使用 System.currentTime 在 TextView 上调用构造函数的时间。事实证明,在我强大的 Alienware PC 上的模拟器中,实例化一个 TextView 对象需要 20-70 毫秒!似乎有什么不对劲,它可能需要这么长时间。

  • 作为引用,布局膨胀、测量和渲染之间存在差异。我现在只关心通货膨胀的表现。

    以下是我如何实现 LayoutInflator.Factory 来进行测量:
            LayoutInflater inflater = LayoutInflater.from(getActivity());
        LayoutInflater inflater2 = inflater.cloneInContext(getActivity());
        inflater2.setFactory(new LayoutInflater.Factory() {
    
            long inner = System.currentTimeMillis();
    
            @Override
            public View onCreateView(String name, Context context, AttributeSet attrs) {
                Log.d(LOG_TAG, "onCreateView: Called factory for " + name + " took " + (System.currentTimeMillis() - inner));
                inner = System.currentTimeMillis();
                return null;
            }
        });
    

    这是输出:
    Called factory for TextView took 34
    Called factory for TextView took 30
    Called factory for android.support.constraint.Guideline took 76
    ...
    

    以下是我如何测量实例化 TextView 和 LayoutParams 对象的时间。
        Log.d(LOG_TAG, "onCreateDialog: 10 " + (System.currentTimeMillis() - last));  last = System.currentTimeMillis();
    
        new TextView(getActivity());
        Log.d(LOG_TAG, "onCreateDialog: 11 " + (System.currentTimeMillis() - last));  last = System.currentTimeMillis();
    
        new ConstraintLayout(getActivity().getApplicationContext());
        Log.d(LOG_TAG, "onCreateDialog: 12 " + (System.currentTimeMillis() - last));  last = System.currentTimeMillis();
    

    这是我的布局,但应用程序中的所有布局似乎都受到了缓慢的影响:
    <?xml version="1.0" encoding="utf-8"?>
    <ScrollView
        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="match_parent">
    
    <android.support.constraint.ConstraintLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content">
    
        <TextView
            android:id="@+id/remote_message_text_view"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="@string/remote_dialog_message"
            android:visibility="gone"
            app:layout_constraintEnd_toEndOf="parent"
            app:layout_constraintStart_toStartOf="parent"
            app:layout_constraintTop_toTopOf="parent"/>
    
        <TextView
            android:id="@+id/building_name_text_view"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:padding="8dp"
            android:textColor="#000"
            android:textSize="32sp"
            android:textStyle="bold"
            app:layout_constraintEnd_toEndOf="parent"
            app:layout_constraintStart_toStartOf="parent"
            app:layout_constraintTop_toBottomOf="@+id/remote_message_text_view"
            tools:text="Bakery"/>
    
        <ImageView
            android:id="@+id/building_icon_image_view"
            android:layout_width="0dp"
            android:layout_height="wrap_content"
            android:adjustViewBounds="true"
            android:contentDescription="@string/building_icon_content_description"
            app:layout_constraintEnd_toEndOf="@+id/right_guide_line"
            app:layout_constraintStart_toStartOf="@+id/left_guide_line"
            app:layout_constraintTop_toBottomOf="@+id/building_name_text_view"
            tools:src="@drawable/bakery"/>
    
        <TextView
            android:id="@+id/action_heading_text_view"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:paddingEnd="8dp"
            android:paddingStart="8dp"
            android:paddingTop="8dp"
            android:text="@string/actions_heading"
            android:textAllCaps="true"
            android:textColor="#000"
            app:layout_constraintStart_toStartOf="parent"
            app:layout_constraintTop_toBottomOf="@+id/building_icon_image_view"/>
    
        <android.support.v7.widget.GridLayout
            android:id="@+id/action_grid_layout"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:paddingEnd="8dp"
            android:paddingStart="8dp"
            app:columnCount="3"
            app:layout_constraintTop_toBottomOf="@+id/action_heading_text_view"
            tools:layout_height="100dp"/>
    
        <TextView
            android:id="@+id/production_rules_heading_text_view"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:paddingEnd="8dp"
            android:paddingStart="8dp"
            android:paddingTop="8dp"
            android:text="@string/production_rules_heading"
            android:textAllCaps="true"
            android:textColor="#000"
            app:layout_constraintStart_toStartOf="parent"
            app:layout_constraintTop_toBottomOf="@+id/action_grid_layout"/>
    
        <TextView
            android:id="@+id/production_rules_text_view"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:paddingEnd="8dp"
            android:paddingStart="8dp"
            app:layout_constraintStart_toStartOf="parent"
            app:layout_constraintTop_toBottomOf="@+id/production_rules_heading_text_view"
            tools:text="1 flour creates 1 bread."/>
    
        <TextView
            android:id="@+id/production_speed_heading_text_view"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:paddingEnd="8dp"
            android:paddingStart="8dp"
            android:paddingTop="8dp"
            android:text="@string/production_speed_heading"
            android:textAllCaps="true"
            android:textColor="#000"
            app:layout_constraintStart_toStartOf="parent"
            app:layout_constraintTop_toBottomOf="@+id/production_rules_text_view"/>
    
        <TextView
            android:id="@+id/production_speed_text_view"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:paddingEnd="8dp"
            android:paddingStart="8dp"
            app:layout_constraintStart_toStartOf="parent"
            app:layout_constraintTop_toBottomOf="@+id/production_speed_heading_text_view"
            tools:text="1 peasant produces 1 unit per 60 minutes.\n(Add a peasant to cut the time to 30 minutes.)"/>
    
        <TextView
            android:id="@+id/countdown_heading_text_view"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:paddingEnd="8dp"
            android:paddingStart="8dp"
            android:paddingTop="8dp"
            android:text="@string/next_unit_count_down_heading"
            android:textAllCaps="true"
            android:textColor="#000"
            android:visibility="gone"
            app:layout_constraintStart_toStartOf="parent"
            app:layout_constraintTop_toBottomOf="@+id/production_speed_text_view"/>
    
        <TextView
            android:id="@+id/countdown_text_view"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:padding="8dp"
            android:textColor="#000"
            android:textSize="32sp"
            app:layout_constraintEnd_toEndOf="parent"
            app:layout_constraintStart_toStartOf="parent"
            app:layout_constraintTop_toBottomOf="@+id/countdown_heading_text_view"
            tools:text="24 : 60 : 60"/>
    
        <android.support.constraint.Guideline
            android:id="@+id/left_guide_line"
            android:layout_width="0dp"
            android:layout_height="match_parent"
            android:orientation="vertical"
            app:layout_constraintGuide_begin="10dp"
            app:layout_constraintGuide_percent=".33"/>
    
        <android.support.constraint.Guideline
            android:id="@+id/right_guide_line"
            android:layout_width="0dp"
            android:layout_height="match_parent"
            android:orientation="vertical"
            app:layout_constraintGuide_percent=".66"/>
    
    </android.support.constraint.ConstraintLayout>
    

    为什么膨胀布局如此缓慢。我怎样才能加快速度?

    最佳答案

    创建 View 只是 LayoutInflater 所做工作的一小部分。您没有初始化它们,没有将它们添加到它们的父级,没有在它们上设置属性,没有创建 LayoutParams,没有进行布局或测量传递。你甚至没有解析 xml。当你做 10% 的工作时,它需要 10% 的时间。你的比较完全没用。

    关于android - 为什么膨胀一个 Android 布局需要这么长时间?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/50977323/

    相关文章:

    .net - EF Code First 和大型模型的性能

    java - 在多个 Activity 中重用布局的最简单方法

    android - 防止 Android ListView 占据几乎所有屏幕高度

    android - 应用程序在模拟器上运行但不能在真实手机上运行

    c++ - C++中声明指针指针的效率

    android - CollapsingToolbarLayout淡出动画速度

    javascript - 如果状态改变, react 会破坏组件中的所有旧 dom 吗?

    Android - ConstraintLayout 中的 ConstraintVertical 权重不起作用?

    Android inflating xml布局产生RuntimeException

    android - 在 Android 和 IOS 之间选择使用哪种音频文件格式?