Android-布局性能:程序化与XML [英] Android - Layouts performance: Programmatic vs XML

查看:115
本文介绍了Android-布局性能:程序化与XML的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

As an Android developer, it bothers me not to know wether an app performance is better by declaring the layouts programmatically or by XML.

我已阅读

I have read this and this question on SO, but none of them answer my question:

性能更高:以编程方式编写布局还是在xml文件中声明布局?

请注意,我只是在询问性能,我不想要基于其他因素的答案.

Note that I'm only asking about performance, I don't want answers based on other factors.

我也在寻找一个非常技术性的答案.如果需要,请提供指向证明您的答案合理的AOSP代码的链接(您可以假定Android版本为棉花糖).更好的方法是指出实验/论文/基准测试,使用两种不同的方式比较巨大布局的加载时间.

Also, I'm looking for a very technical answer. If needed, please provide links to AOSP code that justifies your answer (you can assume that Android version is Marshmallow). Even better would be to point out to an experiment/paper/benchmark were the load time of a huge layout is compared using the two different ways.

推荐答案

对于大多数实际意图和目的,这两种方法都不会对性能产生重大影响.如果您需要膨胀大量的特定布局,这可能是相关的,这时您可以自己对它进行基准测试,看看是否存在任何实际差异,但否则,我很难想象会导致这种情况的情况无论哪种方式都具有重大影响.

For most practical intents and purposes, there is no significant performance impact to either approach. It might be relevant if you needed to inflate an incredibly large number of a particular layout, at which point you might try benchmarking it yourself to see if there's any real difference, but otherwise I'd be hard-pressed to envision a scenario that results in a significant impact either way.

假设您有一个布局:

<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解析要优化得多.

What happens is Android compiles this file into a binary format and packages it in the APK. When you use LayoutInflater at runtime, it will load a block of this binary format into memory and parse it, and build the view hierarchy from the contents, very similar to what you would do by hand in code. That parsing is all done in native code, so it's likely much more optimized than your typical XML parsing in java.

LayoutInflater在遇到标签(例如<Button .../>)时使用反射来构造视图.第一次必须为该特定视图查找构造函数.此后它将缓存构造函数以便以后更快地访问.

LayoutInflater constructs the views using reflection when it encounters a tag (e.g. <Button .../>). The first time it must look up the constructor for that particular view; thereafter it will cache the constructor for faster access later.

通常调用诸如button.setText(...)button.setBackground(...)之类的变体的地方,通常情况下,视图会在通货膨胀期间自行调用这些方法.也就是说,通过视图的构造函数遍历的代码路径将基于从二进制XML格式解析的属性来执行那些更改.这是因为LayoutInflater使用接受AttributeSet的两参数构造函数.这里的含义是,当您手动构建视图时,其中某些方法可能最终被调用两次.

Where you would normally call mutators like button.setText(...), button.setBackground(...), etc., typically the views call these methods on themselves during inflation. That is, the code path being traversed through the view's constructor will perform those mutations based on the attributes parsed from the binary XML format. This is because LayoutInflater uses the two-argument constructor which accepts an AttributeSet. The implication here is that when you build views by hand, some of these methods may end up getting called twice.

例如,以上面的示例布局中的Button.按钮已经具有默认背景(实际上如何提供按钮本身很有趣,但在这里不是很重要),因此,即使仅使用Context调用单参数构造函数,仍会为您提供具有默认背景的Button.换句话说,代码路径包括使用默认背景图像调用setBackground(...)(或某些等效命令)的过程.然后,您必须使用XML文件中命名的自定义可绘制资源自己调用setBackground(...).很难一口气说这会带来什么影响,因为它实际上取决于单个视图的实现以及您要进行的更改.

For example, take the Button in the sample layout above. Buttons already have a default background (how this is actually provided is itself interesting, but not very important here), so even calling the one-argument constructor with just a Context still gets you a Button with the default background. In other words, the code path includes a call to setBackground(...) (or some equivalent) with the default background image. Then later you have to call setBackground(...) yourself with the custom drawable resource named in the XML file. It's difficult to say off hand what impact this has because it really depends on the implementation of individual views and what mutations you are making.

最后一个想法:我已经在一个专业的环境中构建了一个应用程序,该应用程序避免了所有XML的使用(尽可能避免使用XML,包括布局之外的其他东西).我可以毫不犹豫地告诉您,这非常烦人,并且大大增加了开发时间.我非常擅长,它仍然比用XML花费更长的时间.另外:

One final thought: I have built an app in a professional environment that avoided all use of XML (as much as possible, including things other than layouts). I can tell you without hesitation that it is immensely annoying and increases development time dramatically. I'm very good at it and it still takes far longer than doing it in XML. Additionally:

  • 代码往往非常冗长
  • 您没有从IDE中围绕XML布局构建的所有工具中受益
  • 即使没有工具,也只有XML文件可以使您清楚地表示视图层次结构
  • 您可能必须了解UI框架的某些特性(其中某些特性可能取决于API级别)
  • 在Java中并非总是可以将XML属性映射到相应的mutator方法(同样有时取决于API级别)
  • 计算尺寸变得更加有趣
  • 记住伟大的精神体操要在哪里使用LayoutParams

可能还有其他原因,但是这些只是我的头上问题.不要误会我的意思,在很多情况下,手动操作视图和层次结构很有价值,但是我不会用通货膨胀来代替.

There are probably other reasons, but those are just off the top of my head. Don't get me wrong, there are plenty of times where manual manipulation of views and hierarchies is valuable, but I wouldn't substitute inflation for that.

这篇关于Android-布局性能:程序化与XML的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆