24

在我们的一种方法中,我们在列表视图中使用 smoothScrolling。由于此方法在 API Level 8 (FROYO) 之前不可用,因此我们使用 TargetApi 注解来防止在之前的 SDK 版本中调用该方法。

如您所见,我们在类定义和使用类对象的语句中使用了 TargetApi 注释。这比需要的多。

我们的问题是没有考虑 TargetApi 注释,使我们的模拟器在版本 ECLAIR (SDK 7) 中崩溃。通过跟踪,我们才意识到应该只在版本 8+ 中执行的代码也在版本 7 中执行。

我们错过了什么吗?

此代码在侦听器中:

@TargetApi(8)
private final class MyOnMenuExpandListener implements OnMenuExpandListener {
    @Override
    public void onMenuExpanded( int position ) {
        doScrollIfNeeded( position );
    }

    @Override
    public void onMenuCollapsed( int position ) {
        doScrollIfNeeded( position );
    }

    protected void doScrollIfNeeded( int position ) {
        if ( mListViewDocuments.getLastVisiblePosition() - 2 < position ) {
            mListViewDocuments.smoothScrollToPosition( position + 1 );
        }
    }
}

并且侦听器以这种方式注册:

@TargetApi(8)
private void allowSmothScrollIfSupported() {
    if ( Build.VERSION.SDK_INT >= Build.VERSION_CODES.FROYO ) {
        //This if should not be necessary with annotation but it is not taken into account by emulator
        Log.d( LOG_TAG, "Smooth scroll support installed." );
        folderContentAdapter.setOnMenuExpandListener( new MyOnMenuExpandListener() );
    }
}

顺便说一句,我们在调试模式下运行代码,所以这个问题与混淆删除注释无关。

4

3 回答 3

52

@TargetApi不会阻止任何代码运行,它仅用于注释代码并防止新 API 的编译器错误,一旦您知道您只是有条件地调用它们。

您仍然需要添加一些内容

if (Build.VERSION.SDK_INT > 7){
    //...
}
于 2012-08-31T08:25:35.550 回答
5

经过近一年的思考,我想为@Guykun 的回答添加一个小小的补充:

@TargetApi 只会被工具用来告诉开发者“嘿,不要在 XXX android SDK 下使用这个方法”。通常是棉绒。

因此,如果您设计如下方法:

if (Build.VERSION.SDK_INT > 7){
    //...
}

那么您应该将 @TargetApi( 7 ) 添加到您的方法的签名中。

但是,如果您添加 else 语句,并提供一个替代方案,使其适用于所有版本的 Android,例如:

if (Build.VERSION.SDK_INT > 7){
    //...
} else {
    //...
}

那么您不应该@TargetApi( 7 ) 添加到方法的签名中。否则,其他开发人员会认为他们不能使用您的方法 belw api level 7,但实际上,它也适用于他们。

所以必须使用这个注解,用于静态分析,来指示方法支持的最低 api 级别。如:

@TargetApi( 7 )
public void foo() {
   if (Build.VERSION.SDK_INT > 7){
       //...
   else if (Build.VERSION.SDK_INT > 10){
       //...
   } 
}

甚至更好的是,使用android.Build.VERSION_CODES.*.

顺便说一句,您会注意到这对于私有方法确实没有用,除了获得更清晰的代码并有助于在未来推广该方法。

于 2013-08-26T17:48:50.017 回答
1

要在使用针对更高 Api 级别的方法时强制执行 lint 错误,您可以使用RequiresApi代替,TargetApi并且每当您尝试使用该方法而不检查版本代码时,您将收到编译错误。

这就是文档中关于RequiresApi的内容

这与旧的@TargetApi 注释的目的相似,但更清楚地表示这是对调用者的要求,而不是用于“抑制”方法中超过 minSdkVersion 的警告。

于 2016-10-11T18:41:22.340 回答