【发布时间】:2015-01-17 15:51:44
【问题描述】:
我需要在 Android UI 框架中的各种视图类上代理方法,例如 TextView。特别是TextView#setText(int resId)。此方法不是接口的一部分。因此,Java Proxy 将不起作用,因为它仅适用于接口。我需要使用字节码操作。
我发现了一个名为dexmaker 的库,看起来很有希望。我假设我需要进行运行时字节码操作,因为 Android View 类仅在设备上实际可用。 Dexmaker 可以代理具体类的公共方法。然后我注意到TextView#setText(int resId)莫名其妙地是final。 TextView 类本身不是最终的。
我想我可以派生 dexmaker 以支持非最终类中的最终方法。这可能吗?如果不是,我不想开始这个项目。不过,这对我的库来说将是一个巨大的胜利,因为开发人员不需要为他们的视图提供子类、接口或手动静态方法调用。我的图书馆需要知道何时在特定视图上设置了文本。代理是完美的设计模式。
【问题讨论】:
-
随机拍摄(因为它没有被提及):布局充气器允许set a factory class 这可能是你所追求的。这在 probe 中使用,工厂使用 dexmaker 动态创建代理来拦截调用。
-
我的库的一部分实际上使用了布局充气工厂技术。您是说可以在通过 dexmaker 创建的视图对象上设置代理?
-
非常感谢斯特凡。探针源正是我所需要的:)。如果我理解正确,Probe 会创建全新的 View 类,那么 dexmaker Proxybuild 无法处理最终方法的限制不是问题吗?来自 dexmaker ProxyBuilder 文档:“此过程仅适用于具有公共和受保护可见性级别的类。”
-
这应该与dexmaker无关。首先,我将围绕各自的 View 创建包装类,将所有调用转发到真实的 View 实例。然后,您可以根据自己的喜好随意添加呼叫。不知道这条路是否可行,感觉既费力又脆弱。
-
我不认为包装会起作用,因为对象肯定仍然需要正确投射。我怀疑 TextView tv = (TextView) findViewById(R.id.textView) 否则会起作用。最后的方法真的很杀手。除了修补 Android View 类以使用接口之外,还有其他选择吗?
标签: java android javassist bytecode-manipulation