是的,你可以这么做。事实上,方法不止一种。 (注意:此答案中唯一针对 Android 的部分是查找平台版本的方式。)
假设那个班级X
有方法void y()
从 2.0 版本开始,但之前没有。
在不引入任何编译时依赖项的情况下调用此方法的一种方法是使用反射来定位方法并调用invoke
在上面。例如:
X x = ...
if (BUILD.VERSION.RELEASE.compareTo("2.0") >= 0) {
// (exception handling omitted ...)
Method m = c.getClass().getDeclaredMethod("y");
m.invoke(x);
}
另一种方法是为您的应用程序创建版本兼容性适配器 API,如下所示:
/** Version compatibility adapter API */
interface Compat {
void doY();
}
/** Adapter class for version 1 */
class CompatV1 {
public void y(X x) {
// do nothing
}
}
/** Adapter class for version 2 */
class CompatV2 {
public void y(X x) {
x.y();
}
}
//
// Code to instantiate the relevant adapter for the current platform.
//
Class<?> compatClass;
// (Exception handling omitted)
if (BUILD.VERSION.RELEASE.compareTo("2.0") < 0) {
compatClass = Class.forName("...CompatV1");
} else {
compatClass = Class.forName("...CompatV2");
}
// (Exception handling omitted)
Compat compat = (Compat) compatClass.newInstance();
// The adapter object can be passed around as a parameter, wrapped
// as a singleton or injected using dependency injection.
// Invoke X.y() as follows:
X x = ...
compat.y(x);
第二个版本看起来有点重量级,但它的优点是动态(缓慢、非类型安全)代码仅执行一次,并且版本特定代码与其余代码隔离。在现实生活中,您可能会将许多方法放入适配器接口中。
这种方法需要更多的思考,以弄清楚如何设计兼容性 API,以便将版本依赖性与其余代码完全隔离。您可能还需要修改适配器 API,并为每个新的(不兼容的)主要版本创建新的适配器类。
最后,如果平台 API 发生变化,您需要适应需要使用旧版本中的类或方法removed在较新的版本中,那么您将需要编译各种适配器类(例如CompatV*
类)使用不同的 Android SDK。这将使您的构建过程变得更加复杂。
有关此问题的其他“观点”,请阅读 Android 博客上的以下文章:
- Android 应用程序的向后兼容性
-
如何拥有并享用你的(杯形)蛋糕.