我正在为许多Android应用程序创建一个库项目。 应用程序都有一些我希望包含在库项目中的常用功能,但库项目功能需要使用特定于应用程序的常量
所以我正在寻找一种方法来为库函数提供常量的名称,并允许每个应用程序定义它们
特定应用程序常量的示例及其在库项目中的使用方式
public class AppConstants {
public static final long APP_ID = 6;//Needs to be set for each app
}
public static long getCurrentAppId(Context context) {
return getLongPreference(context, CURRENT_APP_ID_KEY, AppConstants.APP_ID);
}
这只是需要为每个应用程序为大量库函数定义的大约60个常量的一个示例
显然我通常会导入/包含项目特定的app_constants.java文件,但这在库项目文件中是不可能的,因为它没有关于特定应用程序的线索(正确地说是这样)
那么让每个特定应用程序覆盖常量的最佳方法是什么?
更新 我花了很长时间决定哪些极好的答案我最满足我的需求(谢谢大家)最后我选择了xml解决方案。我不是特别喜欢它,因为它混乱了我的应用程序资源,我认真考虑使用接口解决方案,但xml解决方案确实很好用
答案 0 :(得分:20)
选项#1 在每个项目中扩展AppConstants类
更好的选择#2 使用XML资源来定义常量
<?xml version="1.0" encoding="utf-8"?>
<resources>
<item type="integer" name="app_id" format="integer">6</item>
</resources>
然后你可以通过
检索它们Context.getResources().getInteger(R.integer.app_id);
将xml文件添加到每个项目的资源中,只需要不同的值
答案 1 :(得分:3)
我不知道有什么好的架构可以做到这一点,但肯定会这样:
在库中定义一些基类
// class, enum or whatever you want it to be.
class BaseConstants {
// use some real singleton instead
public static final BaseConstants instance = new BaseConstants();
// define those values - sadly static inheritance does not work
private static final int APP_ID = 0;
private static final int CURRENT_APP_ID_KEY = 24;
// so we have to do that via methods
protected int getAppId() {
return APP_ID;
}
protected int getAppIdKey() {
return CURRENT_APP_ID_KEY;
}
}
让每个想要自定义的Activity实现
class App1Constants extends BaseConstants {
public static final App1Constants instance = new App1Constants();
private final static int APP_ID = 1;
// want a different APP_ID here.
protected int getAppId() {
return APP_ID;
}
// getAppIdKey not implemented here, uses default
}
将该类用作库的常量的上下文
class Library {
public static long getCurrentAppId(Context context, BaseConstants settings) {
return getLongPreference(context, settings.getAppIdKey(), settings.getAppId());
}
}
活动就像这样
class myActivity extends Activity {
// each Activity can implement it's own constants class and overwrite only some values
private static final BaseConstants CONSTANTS = App1Constants.instance;
private void whatever() {
long appId = Library.getCurrentAppId(this, CONSTANTS);
}
}
class myActivity2 extends Activity {
// or could just use the default ones
private static final BaseConstants CONSTANTS = BaseConstants.instance;
private void whatever() {
long appId = Library.getCurrentAppId(this, CONSTANTS);
}
}
该架构有点难看,但它至少可以起作用
答案 2 :(得分:1)
将它们定义为库项目中的枚举,如
public enum Planet { MERCURY, VENUS, MARS }
android适当采用另一种方法,可怕的常量接口,比如,
interface Planets {
static final int MERCURY = 1;
static final int VENUS = 2;
...
}
然而,这是一个众所周知的java反模式(常量接口,并在Effective Java中有详细介绍,我引用,
常量接口模式是接口的不良使用。那个 class在内部使用一些常量是一个实现细节。 实现常量接口会导致此实现细节 泄漏到类的导出API中。它并不重要 类实现常量接口的类的用户。在 事实上,它甚至可能使他们感到困惑。更糟糕的是,它代表了一种承诺:如果 在将来的版本中,类被修改,以便它不再需要 要使用常量,它仍然必须实现接口以确保 二进制兼容性如果非最终类实现常量 接口,它的所有子类都会污染它们的名称空间 通过界面中的常量。
如果由于某种原因需要常量来获取int值,并且在枚举上调用toString()是不够的,你可以给enum一个额外的信息,比如
public enum ZipCode {
LYNNWOOD(98036), SAN_JOSE(95112), ...;
private int zipCode;
private ZipCode(int zipCode) { this.zipCode = zipCode; }
public int getZipCode() { return zipCode; }
}
请注意,枚举的性能略低于整数常量,但从代码组织和清晰度的角度来看,它们的优越性更高。