我需要在Android UI Framework中的各种视图类上代理方法,例如TextView
。特别是TextView#setText(int resId)
。此方法不是界面的一部分。因此,Java Proxy将无法工作,因为它仅适用于接口。我需要使用字节码操作。
我发现了一个名为dexmaker的图书馆似乎很有希望。我假设我需要进行运行时字节代码操作,因为Android View类实际上只能在设备上使用。 Dexmaker可以在具体类上代理公共方法。然后我注意到TextView#setText(int resId)
莫名其妙地final。 TextView
类本身不是最终的。
我想我可以派遣dexmaker来支持非final类的最终方法。这可能吗?如果不是,我不想启动这个项目。这对我的库来说是一个巨大的胜利,因为开发人员不需要为他们的视图提供子类,接口或手动静态方法调用。我的图书馆需要知道何时在特定视图上设置文本。代理是完美的设计模式。
答案 0 :(得分:2)
" final"的意图是该方法不能被覆盖。这有效地阻止了扩展代理。但是,你仍然可以通过包装代理,就像Spring处理它一样。
这就是将界面与实现分开的最佳实践的原因之一。
更具体地说......
// This snip is not supposed to be functional, only to demonstrate a concept
interface TextViewInterface {
void setText (int resId);
}
class TextView implements TextViewInterface {
public final void setText (int resId) {
... snip ...
}
}
class Proxy$TextView implements TextViewInterface
extends View { // Added this for Android hierarchy
private TextView textView;
public void setText (int resId) {
textView.setText(resId);
}
}
这有帮助吗?
答案 1 :(得分:2)
据我所知,这在Android上无法实现。
Dexmaker创建包含新类的dex文件。然后使用dex类加载器将这些类添加到应用程序中。但是,这些dex文件不能用于替换类,只能添加用作代理的新子类。
从这个意义上讲,dexmaker就像cglib而不是javassist。
请注意,Android既不提供与常规Jvm类似的仪器功能,您可以通过代理重新定义类来检测最终类和方法。 Android不提供此功能:http://developer.android.com/reference/android/app/Instrumentation.html