为了支持不同的 Api 级别,我使用了这里描述的技术:http://android-developers.blogspot.com/2010/07/how-to-have-your-cupcake-and-eat-it-too。 html
这是文章中的示例:
public static VersionedGestureDetector newInstance(Context context,
OnGestureListener listener) {
final int sdkVersion = Integer.parseInt(Build.VERSION.SDK);
VersionedGestureDetector detector = null;
if (sdkVersion < Build.VERSION_CODES.ECLAIR) {
detector = new CupcakeDetector();
} else if (sdkVersion < Build.VERSION_CODES.FROYO) {
detector = new EclairDetector();
} else {
detector = new FroyoDetector(context);
}
detector.mListener = listener;
return detector;
}
这种方法“利用了 ClassLoader 的惰性”。对于具有较新 API 级别的设备(在示例中为 Froyo),它可以使用访问较新版本 API 的 Froyo 类。对于较旧的设备,它们会收到一个仅使用较旧 API 的类。
这完美地工作。
但是,如果您让 FroyoDetector 实现一个仅存在于较新的 api 级别中的接口,则当调用 newInstance() 时,即使在它运行该方法中的任何代码之前,它也会尝试加载 FroyoDetector 实现并放置的接口类日志中显示无法加载 FroyoDetector 类的错误。
所以我的问题是,为什么会发生这种情况?我的印象是,使用这种技术,直到第一次直接引用新类才会加载。detector = new FroyoDetector(context);
但是,如果您向其添加接口,即使不调用该行,它似乎也会尝试加载它。
这是一些重现该问题的代码:
这是一个针对 sdk 16 的应用程序,最小为 8。在 2.3 设备上运行它会重现该问题。
以下是三个类:
public class VersionedLoader {
public static VersionedLoader newInstance() {
if (Build.VERSION.SDK_INT < 12) {
return new OldVersionLoader();
} else {
return new NewVersionLoader();
}
}
}
-
public class OldVersionLoader extends VersionedLoader {
}
-
@TargetApi(11)
public class NewVersionLoader extends VersionedLoader implements AnimatorListener {
@Override
public void onAnimationStart(Animator animation) {}
@Override
public void onAnimationEnd(Animator animation) {}
@Override
public void onAnimationCancel(Animator animation) {}
@Override
public void onAnimationRepeat(Animator animation) {}
}
AnimatorListener 仅从 3.1 开始可用。
现在如果你运行:Object obj = VersionedLoader.newInstance();
此错误将出现在日志中:
10-27 13:51:14.437: I/dalvikvm(7673): Failed resolving Lyour/package/name/NewVersionLoader; interface 7 'Landroid/animation/Animator$AnimatorListener;'
10-27 13:51:14.437: W/dalvikvm(7673): Link of class 'Lyour/package/name/NewVersionLoader;' failed
10-27 13:51:14.445: E/dalvikvm(7673): Could not find class 'your.package.name.NewVersionLoader', referenced from method your.package.name.VersionedLoader.newInstance
10-27 13:51:14.445: W/dalvikvm(7673): VFY: unable to resolve new-instance 1327 (Lyour/package/name/NewVersionLoader;) in Lyour/package/name/VersionedLoader;
10-27 13:51:14.445: D/dalvikvm(7673): VFY: replacing opcode 0x22 at 0x000c
10-27 13:51:14.445: D/dalvikvm(7673): VFY: dead code 0x000e-0011 in Lyour/package/name/VersionedLoader;.newInstance ()Lyour/package/name/VersionedLoader;
它不会崩溃,它实际上会继续正常工作。