【问题标题】:Avoid Internal Getters/Setters避免内部的 getter/setter
【发布时间】:2011-05-31 01:29:58
【问题描述】:

在 Activity.java 的源代码中,我看到下面的一些方法:

public View findViewById(int id) {
    return getWindow().findViewById(id);
}

及getWindow方法的定义:

public Window getWindow() {
    return mWindow;
}

但是按照如下规则:

避免使用内部 Getter/Setter

在 C++ 等本地语言中 使用 getter 的常见做法(例如,我 = getCount()) 而不是直接访问该字段 (i = mCount)。这是 C++ 的一个好习惯,因为 编译器通常可以内联 访问,如果您需要限制或 调试字段访问,您可以添加 随时打码。

在 Android 上,这是一个坏主意。 虚拟方法调用很昂贵, 远不止实例字段 查找。遵循是合理的 常见的面向对象编程 实践并拥有 getter 和 setter 在公共接口中,但在一个 类,您应该始终访问字段 直接。

没有 JIT,直接字段访问是 比调用 a 快大约 3 倍 微不足道的吸气剂。使用 JIT(其中 直接现场访问与 访问本地),直接字段 访问速度大约是 7 倍 调用一个微不足道的吸气剂。这是 在 Froyo 中确实如此,但在 JIT 内联吸气剂的未来 方法。

所以我想知道为什么android开发者不直接访问这个mWindow对象?如果当前android版本的JIT不能内联访问,getWindow().findViewById(id)会比mWindow.findViewById(id)花费更多时间,findViewById是比较常用的方法。

【问题讨论】:

    标签: android mobile


    【解决方案1】:

    我们现在有理由微笑......

    说要避免内部 getter 和 setter 的 android 文档很快就会改变,据说 progruard 已添加到 Gingerbread 平台,该平台可以很好地内联访问器,请参阅 "Avoid Internal Getters/Setters" is bad advice 和这两个 SO 帖子。

    1. https://stackoverflow.com/a/6716573/892055

    2. https://stackoverflow.com/a/4930538/892055

    【讨论】:

      【解决方案2】:

      首先:您无法访问它,因为它是私有的。

      为什么是私有的?

      如您所说,直接访问成员更快。另一方面,您调用的方法不是很快,因为它会在视图层次结构中查找某些视图。因此,就执行该任务所需的总时间百分比而言,使用方法而不是直接访问会产生少量开销。

      反正我相信这是封装的原因。

      您正在调用您不拥有的东西(即Android SDK)。所以,你不应该对“在另一边”发生的事情做出任何假设。只需使用此方法并期望它会返回您想要的视图(如果不存在,则返回 null)。

      也许下一个版本的 android 将使用不同的方法来查找视图,而不是调用 getWindow()。如果您使用此方法,他们(Google/Android)可以简单地将方法标记为已弃用,并将您的调用“转发”到最新的实现。如果您直接调用getWindow(),也许您会寻找不再放置在那里的东西。

      【讨论】:

      • 我不需要一直调用 getWindow() 来评估视图成员。尽管如此,我们是android apis的客户,我想知道他们为什么写这样的代码,为什么不这样,这是值得我关心的。并感谢您的回答。
      • 你没听懂我的意思。在gigerbread 中,findView 可能会使用存储在窗口对象中某处的信息。 Honeycomb google 可能会决定改变视图层次系统并将相应的信息存储在另一个地方,使用其他数据结构的另一种格式。如果直接使用window,新版本将无法使用。如果你使用 findView,google 可以调用新的实现。更多信息:en.wikipedia.org/wiki/…
      • 我的最后一个链接应该是en.wikipedia.org/wiki/…
      【解决方案3】:

      您不能直接访问 mWindow 属性 - it's private。 而且我不会关心findViewById 的速度,因为您只需在onCreate() 方法中为布局中的每个视图调用一次,并将视图存储在您的活动成员中。您确实在每个视图中只调用一次 findViewById,不是吗? ;-)

      但是,如果您真的关心这些事情,您可以自己调用getWindow(),将其存储到局部变量中,然后直接调用findViewById。我不建议这样做,因为您在这里的所有性能提升都不值得花时间,而且无论如何都会在 JIT 的未来版本中过时。

      如果您这样做,我会对您节省的微秒数非常感兴趣。 :-)

      【讨论】:

      • 感谢您的回答。正如你所说,我当然为每个视图调用一次 findViewById。可能是我理解错了原理,现在明白了。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-04-06
      • 2011-01-02
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多