当代码需要某个 API 级别时,为啥 Build.Version 的检查必须是相同的要求,而不是达到或高于要求的级别?

Posted

技术标签:

【中文标题】当代码需要某个 API 级别时,为啥 Build.Version 的检查必须是相同的要求,而不是达到或高于要求的级别?【英文标题】:When code requires an certain API level, why must the check for Build.Version be the same required rather than at or above the required level?当代码需要某个 API 级别时,为什么 Build.Version 的检查必须是相同的要求,而不是达到或高于要求的级别? 【发布时间】:2014-11-29 10:19:03 【问题描述】:

我在观看关于属性动画的 android 开发者视频 (https://www.youtube.com/watch?v=3UbJhmkeSig) 时遇到了一个很容易解决但我很难理解的问题,并希望有人能帮我解释一下。..

我有一个项目在清单中以 API 级别 8 为目标,因此当我使用下面的代码时,我收到一条错误消息,指出所使用的代码需要比当前目标 API 级别更高的 API 级别。作为一种解决方法,我在运行时检查了构建版本 (http://developer.android.com/training/basics/supporting-devices/platforms.html),并且仅在 API 级别足够时才运行代码段。

 if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.ICE_CREAM_SANDWICH) 
        ObjectAnimator rotateAnimation = ObjectAnimator.ofFloat(resp1, View.ROTATION, 270);
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB) 
            rotateAnimation.setRepeatCount(0);
        
    

当我添加第一个最外层的 if 语句时,我产生了困惑。代码行

 ObjectAnimator rotateAnimation = ObjectAnimator.ofFloat(resp1, View.ROTATION, 270);

需要 API 级别 14,因此我检查 Build.Version.ICS 的原因。但是,代码行中的“setRepeatCout()”方法

            rotateAnimation.setRepeatCount(0);

需要 API 11,虽然放在第一个最外面的 if 语句中,用括号确保一个块而不是一行,但我的 IDE (IntelliJ IDEA) 仍然向我显示错误,指出代码行需要 API 11 和我的项目针对 API 8。我的两个解决方案是将代码放入两个嵌套的 if 语句中,一个检查 API 14,另一个检查 API 11,或者使用

@TargetApi(Build.VERSION_CODES.HONEYCOMB)

方法开头的注解。但是,我不完全理解关于它如何影响旧设备的注释,也不理解为什么我需要两个 if 语句来检查构建版本。

-@TargetAPI 是简单地摆脱 lint 检查还是以某种方式影响整个方法以及它是否编译/运行?

-为什么我需要使用两个 if 语句?为什么第一条 if 语句不能满足两行代码?

-是否有理由需要同时使用两个 if 语句来检查构建,或者这可能是一个错误?我尝试在https://youtrack.jetbrains.com/issues/IDEA 搜索已知错误并在谷歌上搜索结果。

非常感谢

【问题讨论】:

【参考方案1】:

@TargetAPI 是简单地摆脱 lint 检查还是以某种方式影响整个方法以及它是否编译/运行?

它向 Lint 表明,对于注解(方法或类)的范围,Lint 应该将 minSdkVersion 视为注解中提供的值(例如,HONEYCOMB),而不是您拥有的任何值在您的清单或build.gradle 文件中指定。

当您作为开发人员验证您正在针对指定的 API 级别正确处理向后兼容性时,您可以申请 @TargetApi。然后,在未来的某个时间,如果您向高于此 API 级别的类或方法添加更多代码,Lint 应该再次对您大喊大叫,因此您意识到您需要添加更多向后兼容性检查。

在这种情况下,正确的解决方案是 @TargetApi(Build.VERSION_CODES.ICE_CREAM_SANDWICH),因为您的代码设置为处理从当前 minSdkVersion 到 API 级别 14 的向后兼容性,但不会更高(因为您没有使用任何有问题的更高)。

为什么我需要使用两个 if 语句?为什么第一个 if 语句不足以满足两行代码?

可能是因为您为 @TargetApi 注释选择了 HONEYCOMB。如果我们在运行 API 级别 14 或更高级别的设备上,我们在定义上运行 API 级别 11 或更高级别的设备上。你不需要内部的if 检查。

是否有理由需要在两个位置检查构建,或者这可能是一个错误?

我不知道您认为“两个位置”是什么。你需要@TargetApi注解和外部if检查吗?是的。你需要两个if 支票吗?不会。而且,如果您将 @TargetApi 设置为 ICE_CREAM_SANDWICH,删除内部的 if 检查并收到 Lint 投诉,这可能是 Android 插件中的错误。

【讨论】:

在使用两个 if 语句时,我没有使用 targetapi 注释。我会使用最外层的 if 语句和 targetAPI 注释或两个 if 语句,但不会同时使用两个 if 语句和注释。我假设外部 if 语句将适用于 if 块内的所有内容..?抱歉,“两个位置”是指两个 if 语句,而不是 if 语句和注释。 @cjayem13:“我假设外部 if 语句将适用于 if 块内的所有内容..?” -- 确实如此。 好的,很好。至少我不会发疯,哈哈。如果一个代码段需要 api 11 而另一个代码段需要 api 14,我想这一定是某种错误,检查 api 14 或更高版本应该对两者都足够了。在验证用户使用 api 14 后我必须检查 api 11 的事实对我来说绝对是荒谬的.. idk,我想我会向 Intellij 报告错误,看看会发生什么.. 感谢您的帮助

以上是关于当代码需要某个 API 级别时,为啥 Build.Version 的检查必须是相同的要求,而不是达到或高于要求的级别?的主要内容,如果未能解决你的问题,请参考以下文章

在 Android Studio 后端设置 API 级别

在下面的代码中,当点击按钮时,为啥不能调用[print("BBB's build function.")]?

当错误说它不应该时,为啥这在 api 21 上有效

如何检查 Android 12 API 级别?

我的Android进阶之旅持续更新:Android开发时需要了解的平台代号,版本,API级别和NDK版本等

我的Android进阶之旅持续更新:Android开发时需要了解的平台代号,版本,API级别和NDK版本等