2012-08-31 131 views
22

在我們的一種方法中,我們在列表視圖中使用了smoothScrolling。由於此方法在API Level 8(FROYO)之前不可用,因此我們使用TargetApi註釋來防止在以前的SDK版本中調用該方法。TargetApi沒有考慮到

如您所見,我們在類定義和使用類的對象的語句中都使用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

順便說一句,你可以寫'@TargetApi(Build.VERSION_CODES.FROYO)'而不是'@TargetApi(8)'。 – Wyzard

+0

你說得對。而且你的targetSDK必須儘可能高。 – Snicolas

回答

50

@TargetApi不會阻止任何代碼的運行,它只是用於註釋代碼並防止新API的編譯器錯誤,一旦您知道您只是有條件地調用它們。

你仍然需要沿着

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

它所做的就是刪除lint錯誤。檢查[這裏](http://tools.android.com/recent/lintapicheckhttp://tools.android.com/recent/lintapicheck) – nandeesh

+0

真的嗎?!它似乎是如此。但是,像我們通常所做的那樣,爲了規避lint錯誤,有一個不同的系統而不是@SuppressWarnings似乎真的很奇怪。 – Snicolas

+0

事實上,這只是另一種形式的註釋,而編程方法允許精確控制運行的內容。 – Guykun

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.*中定義的常量。

順便說一句,你會注意到這對私人方法的確沒用,除非得到一個更清晰的代碼,並有助於在未來推廣該方法。

+0

這是@Tom問題的答案。 – Snicolas

+0

我想和你一樣,但這裏是從Android Studio中的LoginActivity嚮導生成的代碼的摘錄: '@TargetApi(Build.VERSION_CODES.HONEYCOMB_MR2) 私人無效showProgress(最終布爾顯示){ 如果(Build.VERSION。 SDK_INT> = Build.VERSION_CODES.HONEYCOMB_MR2){// ... }其他{ // ... }} ' 只是 – nicobo

+0

使事情更清楚,也許.. – Snicolas

1

要使用有針對性的向更高的API級別的方法時執行皮棉錯誤,你可以使用RequiresApi代替TargetApi,每當你將嘗試使用方法不檢查版本的代碼,你會得到編譯錯誤。

這是documentation說怎麼樣RequiresApi

這是宗旨,以舊的@TargetApi註釋類似,但更 明確表示,這是主叫方的要求, 而不是用來在「超出minSdkVersion」的方法中「抑制」警告。