【问题标题】:Protected fields not visible to subclasses受保护的字段对子类不可见
【发布时间】:2011-06-22 10:05:04
【问题描述】:

我正在编写一个直接扩展android.view.View 的自定义视图。如果我尝试访问字段mScrollXmScrollY,我会看到该字段“无法解析或不是字段”的错误。 source code for android.view.View 具有 mScrollX、mScrollY 和声明为 protected 的类似变量。我的直接子类如何无法访问其父类的受保护字段? (ScrollView 这样的类显然可以。)

附:我意识到我可以打电话给getScrollX(),但我想更新这些字段;打电话给setScroll() 有我不想要的副作用。

【问题讨论】:

  • 奇怪的是,子类,即使在其他包中,也可以访问其超类的受保护变量。我猜你使用的是错误的版本。你能展示一些你的代码吗?

标签: java android subclass protected


【解决方案1】:

这是因为它们不是 Android SDK 的一部分。

这里是mScrollX的源代码:

/**
 * The offset, in pixels, by which the content of this view is scrolled
 * horizontally.
 * {@hide}
 */
@ViewDebug.ExportedProperty(category = "scrolling")
protected int mScrollX;

您会注意到@hide 注释。这意味着这不是 Android SDK 的一部分。创建 Android SDK 的构建过程部分不会将此数据成员包含在您正在编译的 android.jar 文件中的 android.view.View 存根版本中。

@hide 注释用于出于内部目的需要公开或受保护但不被视为 SDK 开发人员应该使用的东西。

请为您遇到的任何问题寻找其他解决方案。

【讨论】:

  • 嗯,有趣!所以套用基本原理:“我们懒得理清适当的封装,所以我们颠覆了语言。”...
  • 我注意到了{@hide} 标签。我认为这就是为什么 mScrollX 没有出现在 JavaDocs 中的原因(比如 proposed @exclude tag,它取代了 @hide)。我没有意识到 SDK 是 API 的存根版本。
  • 我无法理解的一件事是 View 类的受保护变量在 ScrollView 类中被访问。这怎么可能 ?层次结构是 - ScrollView 扩展 FramLayout 扩展 ViewGroup 扩展 View。因此,View 类的 protected 变量只能在 ViewGroup 中访问。
【解决方案2】:

这很简单:注意这些变量上方的@hide 注释。 它是一个特定于 Android 的注释,它对公共 SDK 隐藏字段/方法。这就是你不能直接访问它们的原因。

Romain Guy mentioned it in这个帖子。

【讨论】:

  • 这令人不安。开源有什么意义?所以人们可以阅读源代码并了解发生了什么。但是这里发布的消息是假的?不是生产中使用的那个?这也是可以接受的,如果它是透明的。我不在乎JDK源是否是真实的,但我从阅读中获得的任何信息在真实系统中都必须是真实的。
  • 你必须明白开源的含义。首先,您可以直接从源代码构建自己的 Android 版本,对其进行任何修改,并使用每个方法或字段,无论是否隐藏。这就是手机制造商所做的,以及社区中的一些定制 ROM 厨师。开发人员可以从 Android 开源的另一个方面受益,那就是通过源代码了解幕后工作原理,对我来说,这与文档本身一样重要。
  • 隐藏某些字段或方法的情况通常是以下两种情况之一: 1.可能会在未来的SDK版本中发生变化,因此他们希望减少应用程序不兼容的机会,节省您,开发人员需要大量维护您的应用程序,并且 2. 像在您的情况下直接使用这些字段可能会干扰 API 在内部如何正常工作。
【解决方案3】:

您可以尝试使用反射设置字段:

import java.lang.reflect.Field;

// ...

try {
    Field scrollXField = View.class.getDeclaredField("mScrollX");
    scrollXField.setAccessible(true);
    scrollXField.set(this, myNewValue);
} catch (Exception ex) {
    // oops, android changed the implementation. sucks to be you.
}

但是请注意,当您执行此操作时,您依赖于未记录和不受支持的行为,因此您应该为某些设备或未来版本中出现的问题做好准备。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2013-05-27
    • 2012-08-08
    • 2015-09-05
    • 2021-03-24
    • 2018-02-11
    • 2014-10-09
    • 2018-05-16
    相关资源
    最近更新 更多