Relative paths for imports

6.3k Views Asked by At

I am wondering if there is a way in java to do an import with a relative package path. Something like this:

import *.fragments.MyFragment;

I would use this in cases that I had a whitelabel app in which I wanted to have the main app have one definition of "MyFragment," but a product flavor needed to define it differently.

2

There are 2 best solutions below

1
On

As an extension to @dcow's answer - You can combine flavours in dimensions. So if you wanna have 4 flavours for example and only two variants of view for them - add two more flavours, set them to one dimension, and your initial flavours to another. And after that build any combination you need.

android {
    ...
    flavorDimensions "appversion", "appserver"

    productFlavors {
        free {
            applicationId = "com.myapp.free"
            dimension  "appversion"
        }
        paid {
            applicationId = "com.myapp.paid"
            dimension  "appversion"
        }
        server1{
            dimension  "appserver"
        }
        server2{
            dimension  "appserver"
        }
    }
}
3
On

No.

Classes are fully qualified things. Even if you could import eg. all classes named Object from all packages, the runtime has to know which one you want to use in any given statement. There is absolutely no way for the runtime to know which class you want without a fully qualified name (that is exactly what the import statements are for). And, if two classes share the same canonical name then they are the same class.

To be complete, in vanilla java you can actually load two classes with the same name into the same runtime. You must use a different class loader pointed at different jars, though. You can also cleverly craft classpaths such that you shadow other classes within the same classloader (you'll get the class that comes first on the classpath). But the android build system will not let you dex multiple classes with the same canonical name. You'll get a DexException since everything used to get squeezed into the same classes.dex file. I don't know if this restriction has loosed up in multidex world.

To do what you want, you can simply utilize flavor-specific source sets. So you have src/flavor1/java contain one definition of the class and then src/flavor2/java contain another definition of the same class. If you do this the class cannot be defined in the main source set and must be defined in each and every flavor's source set independently.

Note that flavors generally define types of products and flavor != variant. So you'd want a normal and a whitelabel flavor. In the normal flavor you build with the normal fragment. In whitelabel flavor you build with a different fragement. That's only two different classes.

Beyond that you get into plain old dependency injection and interfaces, which you may choose in order to untie your build philosophy from flavors and gradle's convenient notion of source sets, anyway.