Proxy final method in non-final class

I need proxy methods for different presentation classes in the Android UI Framework, like TextView . Especially TextView#setText(int resId) . This method is not part of the interface. Therefore, Java Proxy will not work because it only works for interfaces. I need to use bytecode manipulation.

I found a library called dexmaker that seemed promising. I assume that I need to perform runtime byte manipulation, since the Android View classes are actually available on the device. Dexmaker can proxy public methods for specific classes. Then I noticed that TextView#setText(int resId) inexplicably final . The TextView class itself is not final.

I think I could develop a dexmaker to support final methods in non-final classes. Is it possible? I do not want to run this project if it is not. This would be a huge victory for my library, although developers would not need subclasses, interfaces, or manual calls to static methods to represent them. My library should know when text is set in a specific view. A proxy server is an ideal design pattern for this.

+5
source share
2 answers

As far as I know, on Android this is not possible.

Dexmaker creates dex files containing the new classes. These classes are then added to the application using dex class loaders. However, such dex files cannot be used to replace classes, only to add new subclasses that serve as proxies.

In this sense, dexmaker is more like cglib than javassist.

Please note that Android does not provide similar toolkit capabilities like regular Jvm, where you can handle final classes and methods by overriding the class through an agent. This is not provided by Android: http://developer.android.com/reference/android/app/Instrumentation.html

+2
source

The goal of "final" is that the method cannot be overridden. This actually stops proxy over extension. However, you can still proxy by wrapping, the Spring method handles it.

This is one of the reasons why it is best to separate an interface from an implementation.

More specific...

 // 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 it help?

+2
source

Source: https://habr.com/ru/post/1211302/


All Articles