I need to proxy methods on various view classes in the Android UI Framework such as TextView
. Particularly TextView#setText(int resId)
. This method is not part of an interface. Therefore, Java Proxy will not work since it only works for interfaces. I need to use bytecode manipulation.
I found a library called dexmaker that seemed promising. I am assuming that I need to do runtime byte code manipulation since the Android View classes are only actually available on the device. Dexmaker can proxy public methods on concrete classes. Then I noticed that TextView#setText(int resId)
is inexplicably final. The TextView
class itself is non-final.
I think I could fork dexmaker to support final methods in non-final classes. Is this possible? I don't want to start this project if it isn't. It would be a huge win for my library though because developers would not need to have subclasses, interfaces, or manual static method calls for their views. My library needs to know when text is set on particular View. A proxy is the perfect design pattern for this.
As far as I know, this is not possible on Android.
Dexmaker creates dex files that contain new classes. These classes are then added to an application by using dex class loaders. Such dex files can however not be used to replace classes, only to add new subclasses that serve as a proxy.
In this sense, dexmaker is rather like cglib than javassist.
Note that Android does neither provide similar instrumentation capabilities as a regular Jvm where you can instrument final classes and methods by class redefinition via an agent. This is not provided by Android: http://developer.android.com/reference/android/app/Instrumentation.html
The intent of "final" is that the method cannot be overridden. That effectively puts a halt to proxying by extension. However, you can still proxy by wrapping, the way Spring handles it.
That is one reason why it is a best practice to separate the interface from the implementation.
In more concrete terms ...
// 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);
}
}
Does this help?
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With