开发者

How to create an "overrideable" configuration in java?

I have two versions of an app based on a common code library project.

The library uses some constant values to determine some runtime configurations, and now I want each app to have a slightly different configuration.

Simplified problem: I have a boolean field in my library project that determines whether or not I display ads in my app. By defaul开发者_Go百科t it's true (as defined in the Library project), and App version A is fine with that. But I need App version B to be add free, so I need to set that value to false.

How can I implement this so that I can essentially override the configuration value in the Library project from the projects that reference the library?

I can change both the library implementation and the referencing project's implementation.

Edit

Also, the configuration boolean only affects the library code's behavior.


A bit late, but I found that this solution works well in my projects. It uses the Android Application class to set a singleton configuration instance that overrides the config of the library.

Config and ConfigInstance below are in the library.

public final class Config {

    public static final boolean VAL;

    private Config() {}

    static {
        // this will be overridden by previous calls to 
        // ConfigInstance.getInstance()
        final ConfigInstance confInstance = ConfigInstance.getInstance(ConfigInstance.DEFAULT_VAL);
        VAL = confInstance.val;
   }

}

// Singleton helper class, be sure not to reference the Config class 
// here so that it is not loaded
public final class ConfigInstance {

    private static volatile ConfigInstance instance = null;

    static final boolean DEFAULT_VAL = false;

    public final boolean val;

    private ConfigInstance(final boolean val) {
        this.val = val;
    }

    // thread safe singleton generator
    public static ConfigInstance getInstance(final boolean val) {
        ConfigInstance result = instance;
        if (result == null) {          // 1st check no lock
            synchronized (ConfigInstance.class) {
                result = instance;
                if (result == null) {  // 2nd check with lock
                    instance = result = new ConfigInstance(val);
                }
            }
        }
        return result;
    }

}

Add the following class to each of the higher level projects, making sure to set the "name" field in the <application> tag in the manifest.

public class ApplicationWrapper extends Application {

    static {
        // this will set the singleton ConfigInstance first, ie. before
        // the library static block is executed; forcing it to use the 
        // values here
        ConfigInstance.getInstance(true);
   }

}

With this, Config.VAL will be set to true in the project.


Just encapsulate the variable in a getter function (getFoo()) and use it through your code. Then override the getter in your subclasses.


Other options include getting the Android package name from your context and making a decision based on that, or pulling a piece of meta-data from your manifest.


You shouldn't be using a constant value in this case. What you should do is create an abstract class with a getter in it and then extend that interface like so:

public abstract class Config {
     public abstract int getValue();
}

public class AppA extends Config {
     private static final int value = 1;

     @Override
     public int getValue(){
         return value;
     }
}

public class AppB extends Config {
     private static final int value = 2;

     @Override
     public int getValue(){
         return value;
     }
}

EDIT: OP added that he needs the configuration value in his library code. I suggest still using this code, but then adding a setter in the library code to take the value returned from this getter in the application setup code.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜