TargetApi没有考虑在内

Sni*_*las 24 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 );
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

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

@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() );
    }
}
Run Code Online (Sandbox Code Playgroud)

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

Guy*_*kun 52

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

你仍然需要添加一些东西

if (Build.VERSION.SDK_INT > 7){
    //...
}
Run Code Online (Sandbox Code Playgroud)

  • @TargetApi不仅是redundent,而且还没有办法正确地注释你给出的例子:没有注释可以附加到违规行,所以它们必须附加到整个函数(或者if语句中的代码必须是变成了fn).为什么Google会添加@TargetApi? (3认同)

Sni*_*las 5

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

@TargetApi将仅被工具用于表示开发人员"嘿,不要在XXX android SDK下使用此方法".通常是棉绒.

所以,如果你设计一个方法,如:

if (Build.VERSION.SDK_INT > 7){
    //...
}
Run Code Online (Sandbox Code Playgroud)

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

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

if (Build.VERSION.SDK_INT > 7){
    //...
} else {
    //...
}
Run Code Online (Sandbox Code Playgroud)

那么你应该加@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){
       //...
   } 
}
Run Code Online (Sandbox Code Playgroud)

甚至更好,使用中定义的常量android.Build.VERSION_CODES.*.

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