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?
Related
I know we can create a package private class in java. So the class is Internal and only accessible in the specified module:
class MyPackagePrivateClass
{
...
}
Now I am developing an android library which i named LibraryA and I wish to use an existing LibraryB in my own LibraryA. How is it possible to prevent user of LibraryA from using the LibraryB directly?
Is there any concept like package private library or anything like that?
Update (For those who ask 'why do I need this?')
In LibraryB there are methods like this:
public QueryBuilder select(String... columns);
But I strongly am of the view that we should use Type-Safe Enum pattern and prevent users from passing strings to these methods(Considering maintenance and refactoring issues). So I decided to wrap those methods in LibraryA:
public TypedQueryBuilder select(Column... columns) {
queryBuilder = queryBuilder.select(toString(columns));
return this;
}
Therefore users of my library should use the Typed methods I provided (Column is a type safe enum here). But if they have access to the original method they may use those instead and I tend to forbid this.
In Java, with polymorphism, you can't hide a public method of an extended class.
I think that you could archive your goal with Facade Pattern: hide all the complex logic and, in this case, control the access and, if needed, implements some interfaces.
Jigsaw project tries to reach the same goal. But it can take long enough to wait until it would be ported to Android. Until then the best solution IMO is to use package private methods. User will be able to understand that he shouldn't use these methods.
Anyway it's impossible to ultimately forbid library user to do certain things, because one can use reflection or substitute class to get rid of nasty restrictions. But it's possible to encourage user not to do certain things - that's what can be done.
Make a jar file out of library B and import it in library A.
https://stackoverflow.com/a/1051705/6897626
I am working with JavaFX, specifically with:
javafx.scene.shape.Rectangle
javafx.scene.shape.Ellipse
javafx.scene.shape.Line
I need additional methods so I created the interface MoreFunctions. I created three new classes that inherit from above classes and implement MoreFunctions, i.e.:
public class MyRectangle extends javafx.scene.shape.Rectangle implements MoreFunctions {
...
}
This is fine as long as MyRectangle and MyEllipse have different implementations of the additional methods. But where do I put methods that have the same implementation? I can't change the parent class since I can't modify the framework. Is a default interface method the only (feasible) way to go? But then what about common attributes that methods rely on?
EDIT: An example of a common method
public void toggleSelection() {
if (!selected) {
setStrokeWidth(5);
setStroke(Color.RED);
selected = true;
}
else {
setStrokeWidth(0);
selected = false;
}
}
This requires
private boolean selected;
It sounds a bit like you are looking for mixin functionality, which doesn't really exist in Java. You might be able to simulate mixins using Java 8 functionality or via a special purpose 3rd party mixin support library.
However, things might be a bit more straight-forward for other developers if you use either pass through methods or composed objects. Each of your Shape subclasses can delegate the functionality to common classes implementing particular functionality (e.g. selection toggling), rather than relying on new language features like default methods.
You can see the difference in inheritable or inherent functionality versus a delegated or compositional approach by examining the way selection capability is handled in various JavaFX classes. ToggleButton has a selectedProperty, so it is directly implementing the selection functionality. However, ListView has a selectionModelProperty, so the selection modeling capability of the ListView is delegated to an associated class, rather than directly implemented in the ListView itself.
Of course, things get a little complicated when you have MVC style systems like JavaFX Controls, but you probably don't need to code your system to that level of complexity. Though, you might want to examine how CSS support is added to controls and consider implementing functions such as styling a selected shape using similar CSS based support, rather than coding the style directly in code.
I was studying some tutorials concerning the Java language. I was wondering if I should abstract every time that I code something, and on any type of standard and stack?
I have seen that with every Spring Services for example, we could even abstract controllers, using interfaces with EJBs on JavaEE stack etc.
I was wondering what is the aim of that? Should I do the same thing while developing with the Android SDK?
Should I abstract every class that I code?
It is always a good idea to make modular, reusable components. When an app is built from the ground up with this in mind, it becomes more and more scalable, more and more self-extensible. The same components in an app get re-used as newer features are added, saving time and effort. And it becomes easier to make changes later on or identify sources of errors. Refactoring should never be afterwards, but from the beginning.
Having said that, it is not a great idea to have more and more abstractions in mobile apps just for the sake of "abstraction". The reason, of course, is that smart phones are not as powerful as servers or even desktop computers. There is a performance penalty associated with literally every class and virtual method in an Android app. There needs to be a greater balance between "abstraction" and efficiency, and the performance trade-offs become more visible on the medium and low-end devices.
From the official docs:
1. Be careful with code abstractions
2. Avoid dependency injection frameworks
3. Avoid Creating Unnecessary Objects
4. Prefer Static Over Virtual
5. Avoid Internal Getters/Setters
EDIT:
After having recently tried out Dagger, I have to admit that point 2 may be a bit outdated by now. What can I say ... I came to the Dagger party quite late.
You need abstraction whenever you have a class that you do not want to implement all of its methods. Those classes inheriting it will be forced to implement all those methods otherwise you would need to declare the subclasses as abstract as well.
In addition to that you should be aware of interface, methods of interface must not have body and the good thing is that your class can implement as much as interface as you want. Whereas, you can only inherit one abstract class. Interfaces are like contracts. Whichever class implement them need to provide body for all of their methods.
Whether you need abstract or interface or both is really depend on your design and what you want to implement. Although it is a good practice to force those classes that have common methods to implement the same interface ( if you do not know anything about body of each of the methods) or abstract ( if you know what the body of some, all or none of the methods)
Another example would be when you have abstraction or interface if you add something to them all the subclasses or classes that are implementing them need to follow those modifications, it means the could would be more easier to get modified.
Have a look at this, this and this and open/close principle as well.
This can be interpreted in many different ways. In my point of view, abstraction is used in coding as a design principle, in cases where you need an extension or many types of implementations. For eg, in Spring, a controller may have defined as an abstract class (A) and have several other types of controllers (B,C,D..) extending A. As a user of Spring framework, If you are not satisfy with the available controller implementations, still you can develop your own controller extending A. Also Spring developers too can extend / add new controllers in future releases with ease.
Reusability. Hands down!
If your class has a
Repetitive code
Non Repetitive codes for different scenarios.
Then it is a good idea to declare the class Abstract.
Put the repetitive code in the abstract class and create abstract methods for the code which is going to be different.
Here is an example.
Register and Unregister any BroadcastReceiver
Abstract class
public abstract class BaseReceiverActivity extends AppCompatActivity{
private BroadCastReceiver receiver;
private IntentFilter filter;
public abstract BroadCastReceiver getReceiver();
public abstract IntentFilter getFilter();
#Override
public void onStart(){
super.onStart();
configureReceiver()
registerReceiver(receiver, filter);
}
#Override
public void onStop(){
super.onPause();
unregisterReceiver(receiver);
}
private void registerMyReceiver(){
registerReceiver(receiver, filter);
}
private void configureReceiver(){
receiver = getReceiver();
filter = getFilter();
}
}
Implementation class:
public class WifiScanner extends BaseReceiverActivity{
#Override
public void onCreate(Bundle sis){
super.onCreate(sis);
setContentView(R.layout.yourLayout);
}
#Override
public BroadCastReceiver getReceiver(){
return new YourReceiver();
}
#Override
public IntentFilter getFilter(){
return IntentFilter(WifiManager.SCAN_RESULTS_AVAILABLE_ACTION));
}
}
After some research I cannot come across the best approach for this. There will be certain color classes that I would like to share amongst multiple projects. Let's call one of them EncryptedColor. Since it is used across multiple projects I don't want multiple copies of it in existence of course. Otherwise I would need to make sure that an update in one location would need to be updated everywhere. However, these classes are needed in some released SDKs that we provide to customers.
How could I design it such that I can use these classes but not provide them with the classes that they don't need access to from their SDK. I don't want useless classes to become visible and flood the smaller subset of classes that they really need to be seeing.
A couple approaches I have thought of so far but aren't quite ideal:
Try and use a doclet structure that hides the calls within the javadoc such as doclava. Javadoc has not fully implemented its own hiding mechanism yet. As I understand this doesn't keep the functions from being visible, but it was mentioned in one spot that you would need reflection to use the calls. I don't see how just the javadoc does that so I must have been missing something.
Android has designed themselves it seems to force reflection from some #hide attributes included in methods that they have in source code. But from the sounds of it, the system hides those and then uses a different jar when it is loading to make those visible at launch time. Probably not useful here.
If I were to keep shared classes in the same package name I could access default and protected members, but...then I am keeping all my classes that use these in the same package name. Not quite ideal either, but it could be done in that manner if I needed to. Might get out of hand with large quantities of shared resources.
What approaches are taken typically in situations such as these? I haven't liked my findings and thought process thus far.
Short answer : you can't hide/remove these classes as they are needed at runtime by your application.
In my opinon, you have 3 alternatives :
Change the classes access to "package private". Yes, doing that doesn't make it impossible to access them, but these classes won't be accessible directly.
Remove the classes and create an API. You want to hide the logic ? Remove it and provide it through a REST API for instance. Depending or your architecture, it could be difficult or impossible.
Create all the instance of these classes in a dynamic way, with Class.forName, using Spring or as in #Steve K answer, with Java's ServiceLoader. As a result, you will be able to remove these classes from the main jar and make them more private, in a way. Again, classes will be here but a little less accessible.
My suggestion that could work would be to implement your color classes as a service using the Java ServiceLoader
You make an interface for your color classes, and implementations can be called using the ServiceLoader class. Then you simply separate your color classes into two packages - a public package you can jar up and distribute with your SDK, and a private package for those classes you want to be internal. The ServiceLoader will find all the color classes available so long as the jar files are in your project's classpath.
For example, if your color classes (as an example) had a common interface like this:
public interface MyAppColor {
public int getRed();
public int getGreen();
public int getBlue();
public int getAlpha();
public void setRed(int red);
public void setGreen(int green);
public void setBlue(int blue);
public void setAlpha(int alpha);
public boolean isValid();
public void doSomething(Object arg);
}
Then you could have a bunch of implementing classes in a jar file, with a service descriptor file included in the jar at the path:
META-INF/services/com.my.app.MyAppColor
The text of that file is simply the list of classes in the jar that implement the interface - one per line:
com.my.app.MyPublicAppColor
com.my.app.MyEncryptedPublicAppColor
com.my.app.MyOtherPublicAppColor
etc. Then all you have to do is make a factory for instantiating the correct type, which could be as simple as this:
public class MyAppColorFactory {
private static ServiceLoader<MyAppColor> serviceLoader = ServiceLoader.load(MyAppColor.class, null);
public static MyAppColor get(String className){
if (className != null){
for (MyAppColor c : serviceLoader){
if (className.equals(c.getClass().getName())){
return c;
}
}
}
return null;
}
}
Deploying only needed code:
- Use Only The Needed Source In Development (1) (2)
Since you have an entire library and many deployments which each use different components, the easiest way to do what you suggest is to use only the sources that you need; not a single library. You can ignore the unused sources. This will only ship the needed code.
- Make The Library "Package Private"
This will allow the access only for the public components of the library and everything else will not be callable. But, it will still ship all the code.
- Create an API as a REST SDK
This will require web access, not desirable for performance code {any code really}. You will ship no sdk code with this method.
- Obfuscate the code
Easy with the correct tools. Obfuscation will change the class and method names in production code to gibberish. This will make the library basically unusable to anyone but you. This will ship all the code but it will be obfuscated
- Native API
You can compile java to machine code and use it in production or as the api. You can also create the api in a native language {not desirable}.
I code java with BlueJ for Mac. I have added the stdlib.jar library (From princeton http://introcs.cs.princeton.edu/java/stdlib/). Before added this library I had my own class named StdDraw.java (The specific class I was using on the project) and copy/pasted the code. I also adjusted some of the code and added some new lines. Since I cannot edit the libraries code, how may I override or extend library classes to add additional functionality?
Since the library classes are final, you can't extend them. Another option is to wrap them in your own classes. For example, you can create your own drawing class that has an instance of StdDraw that it delegates to. For many of your methods you can call the corresponding method of the StdDraw instance, or you can simulate overriding by implementing methods yourself.
Just simply extend the class,
public MyClass extends ClassFromLib
make sure the library jar file is on the classpath. If the author of that class declared it as final indicating that it's not suitable for subclassing. then the best alternative is to use the delegate pattern.
I wrote the code below in this editor so no promises that it complies, but hopefully you get the idea.
public Myclass {
private ClassFromLib cfl = new ClassFromLib();
public void methodA(){
//Do whatever you need here
cfl.methodA(); //Doesn't have to be the same name.
//Do whatever you need here
}
}