2011-05-17 107 views
0

我有一个基于通用代码库项目的应用程序的两个版本。如何在java中创建一个“可覆盖”的配置?

该库使用一些常量值来确定某些运行时配置,现在我希望每个应用程序具有稍微不同的配置。

简化问题:我的库项目中有一个布尔字段,用于确定是否在我的应用中显示广告。默认情况下它是真实的(正如在库项目中定义的那样),而App版本A也可以。但我需要App版本B免费添加,所以我需要将该值设置为false。

我该如何实现这个功能,以便我可以从引用库的项目中覆盖库项目中的配置值?

我可以改变库实现和引用项目的实现。

编辑

此外,配置布尔只影响库代码的行为。

+0

您可以私有化布尔引用并添加一个公共方法,根据需要返回true/false。应用程序版本B可以覆盖以返回false。 – Swati 2011-05-17 20:37:02

+2

如果它不是常量,不要称之为常量。这听起来更像一个配置(有很多方法来创建/使用配置)。 – 2011-05-17 20:39:15

+0

@Swati,我想到了,但它是需要布尔值的库代码,所以它永远不会看到覆盖。 – CodeFusionMobile 2011-05-17 20:41:52

回答

1

只需将变量封装在getter函数(getFoo())中并通过代码使用它即可。然后重写你的子类中的getter。

+0

我想到了这一点,但库代码需要配置变量,而不是版本特定的代码。图书馆将不知道新的子类 – CodeFusionMobile 2011-05-17 20:43:10

+0

哦,不知道当我写我的答案。在这种情况下,您需要实现我的答案,然后通过函数参数将值传递回库中。 – 2011-05-17 20:47:50

0

在这种情况下,您不应该使用常数值。你应该做的是创建一个抽象类中有一个getter和再扩展该接口,像这样:

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; 
    } 
} 

编辑:OP补充说,他需要在自己的代码库的配置价值。我建议仍然使用这个代码,但是在库代码中添加一个setter来从应用程序设置代码中获取这个getter返回的值。

+0

如果AppA代码和AppB代码需要不同的值,则这是正确的方法。但是我需要现有库代码的值以库代码可见的方式进行更改。 – CodeFusionMobile 2011-05-17 20:51:27

+0

看看我的编辑在底部。 – 2011-05-17 20:54:17

1

其他选项包括从您的上下文中获取Android包名称并根据此名称作出决定,或从清单中提取一段元数据。

+0

+1不回答我的直接问题,但可能是我最终会做的 – CodeFusionMobile 2011-05-17 21:23:49

2

有点晚了,但我发现这个解决方案在我的项目中效果很好。它使用Android Application类来设置覆盖库配置的单例配置实例。

ConfigConfigInstance下面是在库中。

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; 
    } 

} 

添加下面的类的每个上级项目,确保设置在清单中的<application>标签中的“名称”字段。

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); 
    } 

} 

有了这个,Config.VAL将在项目设置为true