web-dev-qa-db-ja.com

TargetApiは考慮されていません

私たちの方法の1つでは、リストビューでsmoothScrollingを使用します。このメソッドはAPIレベル8(FROYO)より前では使用できないため、以前のSDKバージョンでメソッドが呼び出されないようにTargetApiアノテーションを使用しました。

ご覧のとおり、doクラス定義とクラスのオブジェクトを使用するステートメントの両方で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() );
    }
}

ところで、コードをデバッグモードで実行しているため、この問題は注釈の難読化とは関係ありません。

24
Snicolas

@TargetApiは、コードの実行を妨げるものではありません。条件付きで呼び出すだけであることがわかったら、コードに注釈を付け、新しいAPIのコンパイラエラーを防ぐためだけのものです。

あなたはまだの線に沿って何かを追加する必要があります

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

これについてもう1年近く考えたので、@ Guykunの答えに小さな補足を追加したいと思います。

@TargetApiは、開発者が「XXX Android SDK」の下でこのメソッドを使用しないでください」と言うためのツールでのみ使用されます。通常はlintです。

したがって、次のようなメソッドを設計する場合:

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

次に、@ TargetApi(7)をメソッドのシグネチャに追加する必要があります。

[〜#〜] but [〜#〜]、elseステートメントを追加し、=のすべてのバージョンで機能する代替手段を提供する場合Android like:

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

次に、notメソッドのシグネチャに@TargetApi(7)を追加する必要があります。そうでなければ、他の開発者は、APIレベル7であなたのメソッドを使用できないと思うでしょうが、実際、それは彼らにとってもうまくいくでしょう。

したがって、静的分析では、このアノテーションを使用して、メソッドでサポートされる最小APIレベルを示す必要があります。のように:

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

さらに良いことに、Android.Build.VERSION_CODES.*で定義された定数を使用します。

ところで、これは、よりクリーンなコードを取得し、将来的にメソッドをパブリックに宣伝するのに役立つことを除いて、プライベートメソッドには実際には役に立たないことに気づいたでしょう。

5
Snicolas

より高いAPIレベルを対象としたメソッドを使用するときにlintエラーを強制するには、 RequiresApi の代わりに TargetApi を使用できます。バージョンコードを確認せずにメソッドを使用しようとすると、コンパイルエラーが発生します。

これは documentationRequiresApi について言っていることです

これは、以前の@TargetApiアノテーションと目的が似ていますが、minSdkVersionを超えるメソッド内の警告を「抑制する」ために使用されるのではなく、これが呼び出し元の要件であることをより明確に表現しています。

1
noob