TargetApi没有考虑在内

时间:2012-08-31 07:52:41

标签: android annotations emulation

在我们的一个方法中,我们在列表视图中使用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() );
    }
}

顺便说一句,我们在调试模式下运行代码,因此问题与模糊删除注释无关。

3 个答案:

答案 0 :(得分:51)

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

你还需要添加一些

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

答案 1 :(得分:5)

经过近一年的思考,我想在@Guykun的回答中添加一些补充:

@TargetApi只会被工具用来说开发者&#34;嘿,不要在XXX android SDK&#34;下面使用这个方法。通常是lint。

所以,如果你设计一个像:

这样的方法
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.*中定义的常量。

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

答案 2 :(得分:1)

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

这是documentation关于RequiresApi

的说法
  

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