为什么Activity中受保护的android:onClick方法实际上起作用了?

30

假设您在 Activity 中定义了 android:onClick="doClick"



protected void doClick(View view) { }
文档指出:这个名称必须对应于一个接受 View 类型的单一参数的公共方法。这是底层 Class.getMethod() 方法的一个给定要求,因为文档指出它仅找到公共方法。

因此,当使用相同的 API 级别时,为什么这个实现在某些设备和模拟器上能够工作,而在其他设备上不能工作呢?


1
它应该不能正常工作。我检查了源代码,他们没有使该方法可访问,这是使用反射访问非公共方法所必需的,也许在不同的API版本中他们有不同的实现。 - Suhaib Roomy
1
@Miquel 都调用了 27.1.1 版本中最新的框架实现 AppCompatViewInflater.DeclaredOnClickListener - tynn
@SuhaibRoomy 如果访问器位于子类或同一包中,则无需将受保护的方法设置为可访问。我猜LieForBananas是正确的,框架可能会创建View实现的运行时代理,使其能够调用#onClick而无需反射。在不起作用的设备上,可能正在尝试调用它而没有进行子类化(使用反射),这将在未调用AccessibleObject#setAccessible的情况下失败。 - Lucas Ross
那么,这个实现本来不可能工作的,你认为受保护的方法不能通过反射调用吗? - Onik
@Onik的getMethod()方法只能找到公共方法。我并不是假设稍后调用该方法是不可能的。我只是想知道如何找到非公共方法。答案是该方法无论如何都是公共的。但只在某些设置中。 - tynn
显示剩余5条评论
2个回答

0
根据 "Java™ 教程": protected 修饰符指定该成员只能在其自己的包内访问(与包私有相同),并且可以被另一个包中其类的子类访问。

2
这个回答与问题有什么关联?问题中描述的受保护的“doClick”方法未被同一包中的类或子类访问;它以某种方式从Android SDK类中访问。 - arcquim

0

我调试了特定的实现。 代码的相关部分在支持库中,使用Class.getMethod()

如文档所述,此方法仅查找公共成员方法并正确运行。由于某种原因,声明为受保护的Activity的所有修饰符(这些是onCreate()doClick())的修改器都设置为1,这意味着这些实际上是公共的。

我只能在Mac上创建debug版本时观察到这种行为。所以这为什么会发生仍然是一个未解之谜,我正在尝试找到答案。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接