Android - 布局性能:程序化与XML

时间:2016-02-23 03:08:15

标签: java android xml performance android-layout

作为一名Android开发人员,通过以编程方式或通过XML声明布局,我不会不知道应用程序性能是否更好。

我在SO上看过thisthis问题,但没有一个回答我的问题:

什么是更高效的:以编程方式编写布局或在xml文件中声明它们?

请注意,我只询问表现,我不想根据其他因素寻求答案。

另外,我正在寻找一个非常技术性的答案。如果需要,请提供AOSP代码的链接以证明您的答案(您可以假设Android版本是Marshmallow)。更好的是指出一个实验/论文/基准是使用两种不同的方式比较巨大布局的加载时间。

1 个答案:

答案 0 :(得分:13)

对于大多数实际意图和目的,对这两种方法都没有显着的性能影响。如果你需要夸大一个特别大的特定布局可能是相关的,此时你可能会尝试自己进行基准测试,看看是否有任何真正的差异,但是否则我很难设想出一个结果的场景无论如何都会产生重大影响。

假设你有一个布局:

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

    <Button
        android:id="@+id/some_button"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:background="@drawable/my_button_bg"
        android:text="Hello World" />

    <!-- other views ... -->

</LinearLayout>

Android会将此文件编译为二进制格式并将其打包到APK中。在运行时使用LayoutInflater时,它会将这个二进制格式的块加载到内存中并对其进行解析,并根据内容构建视图层次结构,这与您在代码中手动执行的操作非常相似。这种解析都是在本机代码中完成的,所以它可能比java中典型的XML解析更加优化。

LayoutInflater在遇到标记时使用反射构建视图(例如<Button .../>)。第一次必须查找该特定视图的构造函数;之后它会缓存构造函数,以便以后更快地访问。

如果您通常会调用button.setText(...)button.setBackground(...)等变体,通常情况下,视图会在通胀期间调用这些方法。也就是说,遍历视图构造函数的代码路径将根据从二进制XML格式解析的属性执行这些突变。这是因为LayoutInflater使用接受AttributeSet的双参数构造函数。这里的含义是,当您手动构建视图时,其中一些方法最终可能会被调用两次。

例如,在上面的示例布局中选择Button。按钮已经有一个默认的背景(这实际上是如何提供它本身很有趣,但在这里不是很重要),所以即使只用一个Context调用一个参数的构造函数仍然会得到一个Button默认背景。换句话说,代码路径包括使用默认背景图像调用setBackground(...)(或某些等效物)。然后,您必须使用XML文件中指定的自定义可绘制资源自行调用setBackground(...)。现在很难说出这有什么影响,因为它实际上取决于个人观点的实施以及你正在做出的突变。

最后一个想法:我在专业环境中构建了一个应用程序,避免了所有XML的使用(尽可能多,包括布局以外的东西)。我可以毫不犹豫地告诉你它非常烦人并且大大增加了开发时间。我非常擅长它,它比用XML做的还要长。此外:

  • 代码往往非常冗长
  • 您无法获得IDE中围绕XML布局构建的所有工具的好处
  • 即使没有工具,只需单独使用XML文件就可以清楚地表示视图层次结构
  • 您可能必须了解UI框架的某些特性(其中一些可能取决于API级别)
  • 并不总是可以将XML属性映射到java中相应的mutator方法(有时还取决于API级别)
  • 计算尺寸变得更有趣
  • 记住哪些LayoutParams可以在哪里使用伟大的心理体操

可能有其他原因,但这些只是我的头脑。不要误解我的意思,有很多时候手动操纵视图和层次结构是有价值的,但我不会用通胀代替。

相关问题