Codeüberprüfung mit Anmerkungen verbessern

Mithilfe von Code-Prüftools wie lint können Sie Probleme finden und Ihren Code verbessern. Allerdings können Prüftools nur begrenzte Rückschlüsse ziehen. Android-Ressourcen-IDs verwenden beispielsweise ein int, um Strings, Grafiken, Farben und andere Ressourcentypen zu identifizieren. Prüftools können daher nicht erkennen, ob Sie anstelle einer Farbe eine Stringressource angegeben haben. In diesem Fall wird Ihre App möglicherweise falsch gerendert oder kann gar nicht ausgeführt werden, auch wenn Sie die Codeprüfung verwenden.

Mit Anmerkungen können Sie Code-Prüftools wie Lint Hinweise geben, um diese subtileren Codeprobleme zu erkennen. Anmerkungen werden als Metadaten-Tags hinzugefügt, die Sie an Variablen, Parameter und Rückgabewerte anhängen, um Methodenrückgabewerte, übergebene Parameter, lokale Variablen und Felder zu prüfen. In Kombination mit Code-Prüftools können Anmerkungen Ihnen helfen, Probleme wie Nullzeigerausnahmen und Ressourcentypkonflikte zu erkennen.

Android unterstützt eine Vielzahl von Anmerkungen über die Jetpack-Anmerkungsbibliothek. Sie können über das Paket androidx.annotation auf die Bibliothek zugreifen.

Hinweis:Wenn ein Modul von einem Anmerkungs-Prozessor abhängt, müssen Sie entweder die Abhängigkeitskonfiguration kapt oder ksp für Kotlin oder die Abhängigkeitskonfiguration annotationProcessor für Java verwenden, um diese Abhängigkeit hinzuzufügen.

Ihrem Projekt Anmerkungen hinzufügen

Wenn Sie Anmerkungen in Ihrem Projekt aktivieren möchten, fügen Sie Ihrer Bibliothek oder App die Abhängigkeit androidx.annotation:annotation hinzu. Alle hinzugefügten Anmerkungen werden geprüft, wenn Sie eine Codeüberprüfung oder lint-Aufgabe ausführen.

Bibliotheksabhängigkeit für Jetpack-Anmerkungen hinzufügen

Die Jetpack-Anmerkungsbibliothek wird im Maven-Repository von Google veröffentlicht. Wenn Sie Ihrem Projekt die Jetpack-Anmerkungsbibliothek hinzufügen möchten, fügen Sie in der Datei build.gradle oder build.gradle.kts im Block dependencies die folgende Zeile ein:

Kotlin

dependencies {
    implementation("androidx.annotation:annotation:1.9.1")
}

Groovy

dependencies {
    implementation 'androidx.annotation:annotation:1.9.1'
}
Klicken Sie dann in der Symbolleiste oder in der angezeigten Synchronisierungsbenachrichtigung auf Jetzt synchronisieren.

Wenn Sie Anmerkungen in Ihrem eigenen Bibliotheksmodul verwenden, werden die Anmerkungen als Teil des Android-Archiv-Artefakts (AAR) im XML-Format in der Datei annotations.zip eingefügt. Durch das Hinzufügen der androidx.annotation-Abhängigkeit wird keine Abhängigkeit für Downstream-Nutzer Ihrer Bibliothek eingeführt.

Hinweis:Wenn Sie andere Jetpack-Bibliotheken verwenden, müssen Sie die Abhängigkeit androidx.annotation möglicherweise nicht hinzufügen. Da viele andere Jetpack-Bibliotheken von der Anmerkungsbibliothek abhängen, haben Sie möglicherweise bereits Zugriff auf die Anmerkungen.

Eine vollständige Liste der Anmerkungen im Jetpack-Repository finden Sie in der Referenzbibliothek für Jetpack-Anmerkungen. Alternativ können Sie die automatische Vervollständigung verwenden, um die verfügbaren Optionen für die import androidx.annotation.-Anweisung aufzurufen.

Codeprüfungen ausführen

Wenn Sie eine Codeprüfung in Android Studio starten möchten, die die Validierung von Anmerkungen und die automatische Lint-Prüfung umfasst, wählen Sie im Menü Analysieren > Code prüfen aus. Android Studio zeigt Konfliktmeldungen an, um potenzielle Probleme zu melden, bei denen Ihr Code mit Anmerkungen in Konflikt steht, und um mögliche Lösungen vorzuschlagen.

Sie können Anmerkungen auch erzwingen, indem Sie die Aufgabe lint über die Befehlszeile ausführen. Das kann zwar nützlich sein, um Probleme mit einem Continuous Integration-Server zu melden, aber die lint-Aufgabe erzwingt keine Anmerkungen zur Nullwertprüfung (im nächsten Abschnitt beschrieben). Das geschieht nur in Android Studio. Weitere Informationen zum Aktivieren und Ausführen von Lint-Prüfungen finden Sie unter Code mit lint-Prüfungen verbessern.

Anmerkungskonflikte führen zwar zu Warnungen, diese verhindern jedoch nicht, dass Ihre App kompiliert wird.

Anmerkungen zur Nullwertigkeit

Anmerkungen zur Nullwertigkeit können in Java-Code hilfreich sein, um festzulegen, ob Werte null sein dürfen. In Kotlin-Code sind sie weniger nützlich, da Kotlin integrierte Regeln zur Null-Zulässigkeit hat, die zur Kompilierungszeit erzwungen werden.

Fügen Sie @Nullable- und @NonNull-Anmerkungen hinzu, um zu prüfen, ob eine bestimmte Variable, ein bestimmter Parameter oder ein bestimmter Rückgabewert null ist. Die Anmerkung @Nullable gibt eine Variable, einen Parameter oder einen Rückgabewert an, der null sein kann. @NonNull gibt eine Variable, einen Parameter oder einen Rückgabewert an, der nicht null sein darf.

Wenn beispielsweise eine lokale Variable mit einem Nullwert als Parameter an eine Methode übergeben wird, die mit der Anmerkung @NonNull versehen ist, wird beim Erstellen des Codes eine Warnung ausgegeben, die auf einen Konflikt mit einem nicht nullwertigen Wert hinweist. Wenn Sie versuchen, auf das Ergebnis einer mit @Nullable gekennzeichneten Methode zu verweisen, ohne vorher zu prüfen, ob das Ergebnis null ist, wird eine Null-Warnung ausgegeben. Verwenden Sie @Nullable nur für den Rückgabewert einer Methode, wenn jede Verwendung der Methode explizit auf Null geprüft werden muss.

Das folgende Beispiel zeigt die Nullbarkeit in der Praxis. Im Kotlin-Beispielcode wird die @NonNull-Anmerkung nicht verwendet, da sie dem generierten Bytecode automatisch hinzugefügt wird, wenn ein nicht nullwertiger Typ angegeben wird. Im Java-Beispiel wird die @NonNull-Anmerkung für die Parameter context und attrs verwendet, um zu prüfen, ob die übergebenen Parameterwerte nicht null sind. Außerdem wird geprüft, ob die onCreateView()-Methode selbst nicht null zurückgibt:

Kotlin

...
    /** Annotation not used because of the safe-call operator(?)**/
    override fun onCreateView(
            name: String?,
            context: Context,
            attrs: AttributeSet
    ): View? {
        ...
    }
...

Java

import androidx.annotation.NonNull;
...
    /** Add support for inflating the <fragment> tag. **/
    @NonNull
    @Override
    public View onCreateView(String name, @NonNull Context context,
      @NonNull AttributeSet attrs) {
      ...
      }
...

Analyse der Null-Zulässigkeit

Android Studio unterstützt die Ausführung einer Nullbarkeitsanalyse, um Null-Anmerkungen automatisch abzuleiten und in Ihren Code einzufügen. Bei einer Analyse der Nullbarkeit werden die Verträge in den Methodenhierarchien in Ihrem Code geprüft, um Folgendes zu erkennen:

  • Methoden aufrufen, die null zurückgeben können
  • Methoden, die keinen Nullwert zurückgeben sollten.
  • Variablen wie Felder, lokale Variablen und Parameter, die null sein können.
  • Variablen wie Felder, lokale Variablen und Parameter, die keinen Nullwert enthalten können.

Die entsprechenden Null-Anmerkungen werden dann automatisch an den erkannten Stellen eingefügt.

Wenn Sie in Android Studio eine Analyse der Nullbarkeit ausführen möchten, wählen Sie Analysieren > Nulle inferieren aus. Android Studio fügt die Android-Anmerkungen @Nullable und @NonNull an den erkannten Stellen in Ihrem Code ein. Nach einer Null-Analyse sollten Sie die eingefügten Anmerkungen überprüfen.

Hinweis:Wenn Sie Anmerkungen zur Nullverweisbarkeit hinzufügen, werden bei der automatischen Vervollständigung möglicherweise die IntelliJ-Anmerkungen @Nullable und @NotNull anstelle der Android-Anmerkungen zur Nullverweisbarkeit vorgeschlagen und die entsprechende Bibliothek automatisch importiert. Der Lint-Checker von Android Studio sucht jedoch nur nach den Null-Anmerkungen von Android. Prüfen Sie bei der Überprüfung Ihrer Anmerkungen, ob in Ihrem Projekt die Android-Nullanmerkungen verwendet werden, damit der Lint-Checker Sie bei der Codeprüfung richtig benachrichtigen kann.

Ressourcenanmerkungen

Die Validierung von Ressourcentypen kann nützlich sein, da Android-Referenzen auf Ressourcen wie drawable- und string-Ressourcen als Ganzzahlen übergeben werden.

Code, in dem ein Parameter auf einen bestimmten Ressourcentyp verweisen soll, z. B. auf eine String, kann an den erwarteten Referenztyp int übergeben werden, verweist aber tatsächlich auf einen anderen Ressourcentyp, z. B. auf eine R.string-Ressource.

Sie können beispielsweise @StringRes-Anmerkungen hinzufügen, um zu prüfen, ob ein Ressourcenparameter eine R.string-Referenz enthält, wie hier gezeigt:

Kotlin

abstract fun setTitle(@StringRes resId: Int)

Java

public abstract void setTitle(@StringRes int resId)

Bei der Codeprüfung wird durch die Anmerkung eine Warnung generiert, wenn im Parameter keine R.string-Referenz übergeben wird.

Anmerkungen für andere Ressourcentypen wie @DrawableRes, @DimenRes, @ColorRes und @InterpolatorRes können mit demselben Anmerkungsformat hinzugefügt und während der Codeprüfung ausgeführt werden.

Wenn Ihr Parameter mehrere Ressourcentypen unterstützt, können Sie für einen bestimmten Parameter mehrere Anmerkungen zu Ressourcentypen hinzufügen. Verwenden Sie @AnyRes, um anzugeben, dass der kommentierte Parameter beliebiger Art sein kann.R

Sie können zwar mit @ColorRes angeben, dass ein Parameter eine Farbressource sein soll, aber eine Farbganzzahl (im Format RRGGBB oder AARRGGBB) wird nicht als Farbressource erkannt. Verwenden Sie stattdessen die Anmerkung @ColorInt, um anzugeben, dass ein Parameter eine Farbganzzahl sein muss. Die Build-Tools kennzeichnen fehlerhaften Code, der annotierten Methoden eine Farbressourcen-ID wie android.R.color.black statt einer Farb-Integer-Zahl übergibt.

Anmerkungen zu Threads

Mit Thread-Anmerkungen wird geprüft, ob eine Methode von einem bestimmten Thread aufgerufen wird. Die folgenden Thread-Hinweise werden unterstützt:

Die Build-Tools behandeln die @MainThread- und @UiThread-Anmerkungen als austauschbar. Sie können also @UiThread-Methoden aus @MainThread-Methoden und umgekehrt aufrufen. Bei System-Apps mit mehreren Ansichten in verschiedenen Threads kann sich ein UI-Thread jedoch vom Hauptthread unterscheiden. Daher sollten Sie Methoden, die mit der Ansichtshierarchie einer App verknüpft sind, mit @UiThread und nur Methoden, die mit dem Lebenszyklus einer App verknüpft sind, mit @MainThread annotieren.

Wenn alle Methoden in einer Klasse dieselbe Threadanforderung haben, können Sie der Klasse eine einzelne Threadanmerkung hinzufügen, um zu prüfen, ob alle Methoden in der Klasse von demselben Threadtyp aufgerufen werden.

Eine gängige Verwendung von Thread-Anmerkungen besteht darin, zu prüfen, ob Methoden oder Klassen, die mit @WorkerThread annotiert sind, nur von einem geeigneten Hintergrund-Thread aufgerufen werden.

Anmerkungen zu Werteinschränkungen

Verwenden Sie die Anmerkungen @IntRange, @FloatRange und @Size, um die Werte der übergebenen Parameter zu validieren. Sowohl @IntRange als auch @FloatRange sind am nützlichsten, wenn sie auf Parameter angewendet werden, bei denen Nutzer den Bereich wahrscheinlich falsch eingeben.

Mit der Anmerkung @IntRange wird geprüft, ob ein Ganzzahl- oder Long-Parameterwert innerhalb eines bestimmten Bereichs liegt. Im folgenden Beispiel wird angegeben, dass der Parameter alpha einen Ganzzahlwert zwischen 0 und 255 enthalten muss:

Kotlin

fun setAlpha(@IntRange(from = 0, to = 255) alpha: Int) { ... }

Java

public void setAlpha(@IntRange(from=0,to=255) int alpha) { ... }

Mit der Anmerkung @FloatRange wird geprüft, ob ein Float- oder Double-Parameterwert innerhalb eines bestimmten Bereichs von Gleitkommawerten liegt. Im folgenden Beispiel wird angegeben, dass der Parameter alpha einen Gleitkommawert zwischen 0,0 und 1,0 enthalten muss:

Kotlin

fun setAlpha(@FloatRange(from = 0.0, to = 1.0) alpha: Float) {...}

Java

public void setAlpha(@FloatRange(from=0.0, to=1.0) float alpha) {...}

Mit der Anmerkung @Size wird die Größe einer Sammlung oder eines Arrays oder die Länge eines Strings geprüft. Mit der Anmerkung @Size können Sie die folgenden Qualitäten überprüfen:

  • Mindestgröße, z. B. @Size(min=2)
  • Maximale Größe, z. B. @Size(max=2)
  • Genaue Größe, z. B. @Size(2)
  • Eine Zahl, ein Vielfaches der Größe, z. B. @Size(multiple=2)

Mit @Size(min=1) wird beispielsweise geprüft, ob eine Sammlung nicht leer ist, und mit @Size(3) wird überprüft, ob ein Array genau drei Werte enthält.

Im folgenden Beispiel ist zu sehen, dass das Array location mindestens ein Element enthalten muss:

Kotlin

fun getLocation(button: View, @Size(min=1) location: IntArray) {
    button.getLocationOnScreen(location)
}

Java

void getLocation(View button, @Size(min=1) int[] location) {
    button.getLocationOnScreen(location);
}

Berechtigungshinweise

Verwenden Sie die Anmerkung @RequiresPermission, um die Berechtigungen des Aufrufers einer Methode zu prüfen. Wenn Sie prüfen möchten, ob eine bestimmte Berechtigung aus einer Liste gültiger Berechtigungen vorhanden ist, verwenden Sie das Attribut anyOf. Verwenden Sie das Attribut allOf, um nach einer Reihe von Berechtigungen zu suchen. Im folgenden Beispiel wird die Methode setWallpaper() mit einer Anmerkung versehen, die angibt, dass der Aufrufer der Methode die Berechtigung permission.SET_WALLPAPERS haben muss:

Kotlin

@RequiresPermission(Manifest.permission.SET_WALLPAPER)
@Throws(IOException::class)
abstract fun setWallpaper(bitmap: Bitmap)

Java

@RequiresPermission(Manifest.permission.SET_WALLPAPER)
public abstract void setWallpaper(Bitmap bitmap) throws IOException;

Im folgenden Beispiel muss der Aufrufer der copyImageFile()-Methode sowohl Lesezugriff auf den externen Speicher als auch Lesezugriff auf die Standortmetadaten im kopierten Bild haben:

Kotlin

@RequiresPermission(allOf = [
    Manifest.permission.READ_EXTERNAL_STORAGE,
    Manifest.permission.ACCESS_MEDIA_LOCATION
])
fun copyImageFile(dest: String, source: String) {
    ...
}

Java

@RequiresPermission(allOf = {
    Manifest.permission.READ_EXTERNAL_STORAGE,
    Manifest.permission.ACCESS_MEDIA_LOCATION})
public static final void copyImageFile(String dest, String source) {
    //...
}

Legen Sie die Berechtigungsanforderung für Berechtigungen für Intents in das Stringfeld fest, das den Namen der Intent-Aktion definiert:

Kotlin

@RequiresPermission(android.Manifest.permission.BLUETOOTH)
const val ACTION_REQUEST_DISCOVERABLE = "android.bluetooth.adapter.action.REQUEST_DISCOVERABLE"

Java

@RequiresPermission(android.Manifest.permission.BLUETOOTH)
public static final String ACTION_REQUEST_DISCOVERABLE =
            "android.bluetooth.adapter.action.REQUEST_DISCOVERABLE";

Wenn für Inhaltsanbieter separate Berechtigungen für Lese- und Schreibzugriff erforderlich sind, setzen Sie jede Berechtigungsanforderung in eine Anmerkung vom Typ @RequiresPermission.Read oder @RequiresPermission.Write:

Kotlin

@RequiresPermission.Read(RequiresPermission(READ_HISTORY_BOOKMARKS))
@RequiresPermission.Write(RequiresPermission(WRITE_HISTORY_BOOKMARKS))
val BOOKMARKS_URI = Uri.parse("content://browser/bookmarks")

Java

@RequiresPermission.Read(@RequiresPermission(READ_HISTORY_BOOKMARKS))
@RequiresPermission.Write(@RequiresPermission(WRITE_HISTORY_BOOKMARKS))
public static final Uri BOOKMARKS_URI = Uri.parse("content://browser/bookmarks");

Indirekte Berechtigungen

Wenn eine Berechtigung vom Wert abhängt, der für den Parameter einer Methode angegeben wurde, verwenden Sie @RequiresPermission für den Parameter selbst, ohne die Berechtigungen aufzulisten. Die Methode startActivity(Intent) verwendet beispielsweise eine indirekte Berechtigung für die Intent-Instanz, die an die Methode übergeben wird:

Kotlin

abstract fun startActivity(@RequiresPermission intent: Intent, bundle: Bundle?)

Java

public abstract void startActivity(@RequiresPermission Intent intent, @Nullable Bundle)

Wenn Sie indirekte Berechtigungen verwenden, führen die Build-Tools eine Datenflussanalyse durch, um zu prüfen, ob das an die Methode übergebene Argument @RequiresPermission-Anmerkungen enthält. Anschließend werden alle vorhandenen Anmerkungen aus dem Parameter auf die Methode selbst angewendet. Im Beispiel für startActivity(Intent) führen Anmerkungen in der Klasse Intent zu Warnungen bei ungültiger Verwendung von startActivity(Intent), wenn der Methode ein Intent ohne die entsprechenden Berechtigungen übergeben wird, wie in Abbildung 1 dargestellt.

Abbildung 1: Die Warnung wurde durch eine indirekte Berechtigungsannotation für die startActivity(Intent)-Methode generiert.

Die Build-Tools generieren die Warnung für startActivity(Intent) aus der Anmerkung zum entsprechenden Intent-Aktionsnamen in der Intent-Klasse:

Kotlin

@RequiresPermission(Manifest.permission.CALL_PHONE)
const val ACTION_CALL = "android.intent.action.CALL"

Java

@RequiresPermission(Manifest.permission.CALL_PHONE)
public static final String ACTION_CALL = "android.intent.action.CALL";

Bei Bedarf können Sie @RequiresPermission anstelle von @RequiresPermission.Read oder @RequiresPermission.Write verwenden, wenn Sie den Parameter einer Methode annotieren. Bei indirekten Berechtigungen sollte @RequiresPermission jedoch nicht in Verbindung mit den Anmerkungen für Lese- oder Schreibberechtigungen verwendet werden.

Anmerkungen zu Rückgabewerten

Mit der Anmerkung @CheckResult können Sie prüfen, ob das Ergebnis oder der Rückgabewert einer Methode tatsächlich verwendet wird. Anstatt jede nicht-void-Methode mit @CheckResult zu annotieren, fügen Sie die Anmerkung hinzu, um die Ergebnisse potenziell verwirrender Methoden zu verdeutlichen.

Neue Java-Entwickler denken beispielsweise oft fälschlicherweise, dass <String>.trim() Leerzeichen aus dem ursprünglichen String entfernt. Wenn Sie die Methode mit @CheckResult-Flags annotieren, wird <String>.trim() verwendet, wenn der Aufrufer nichts mit dem Rückgabewert der Methode macht.

Im folgenden Beispiel wird die Methode checkPermissions() mit Anmerkungen versehen, um zu prüfen, ob auf den Rückgabewert der Methode tatsächlich verwiesen wird. Außerdem wird die Methode enforcePermission() als Ersatzmethode für den Entwickler vorgeschlagen:

Kotlin

@CheckResult(suggest = "#enforcePermission(String,int,int,String)")
abstract fun checkPermission(permission: String, pid: Int, uid: Int): Int

Java

@CheckResult(suggest="#enforcePermission(String,int,int,String)")
public abstract int checkPermission(@NonNull String permission, int pid, int uid);

CallSuper-Anmerkungen

Mit der @CallSuper-Anmerkung können Sie prüfen, ob eine überschreibende Methode die Superimplementierung der Methode aufruft.

Im folgenden Beispiel wird die Methode onCreate() annotiert, damit alle überschreibenden Methodenimplementierungen super.onCreate() aufrufen:

Kotlin

@CallSuper
override fun onCreate(savedInstanceState: Bundle?) {
}

Java

@CallSuper
protected void onCreate(Bundle savedInstanceState) {
}

Typdef-Anmerkungen

Mit Typdef-Anmerkungen wird geprüft, ob ein bestimmter Parameter, Rückgabewert oder ein Feld auf eine bestimmte Gruppe von Konstanten verweist. Außerdem wird die Codevervollständigung aktiviert, um automatisch die zulässigen Konstanten anzubieten.

Verwenden Sie die Anmerkungen @IntDef und @StringDef, um aufgezählte Anmerkungen von Ganzzahl- und Stringmengen zu erstellen, um andere Arten von Codereferenzen zu validieren.

Bei Typdefinitionen wird @interface verwendet, um den neuen typisierten Anmerkungstyp zu deklarieren. Die @IntDef- und @StringDef-Anmerkungen sowie @Retention werden für die neue Anmerkung verwendet und sind erforderlich, um den Typ der Aufzählung zu definieren. Die @Retention(RetentionPolicy.SOURCE)-Anmerkung weist den Compiler an, die aufgezählten Anmerkungsdaten nicht in der .class-Datei zu speichern.

Im folgenden Beispiel wird gezeigt, wie eine Anmerkung erstellt wird, die prüft, ob ein als Methodenparameter übergebener Wert auf eine der definierten Konstanten verweist:

Kotlin

import androidx.annotation.IntDef
//...
// Define the list of accepted constants and declare the NavigationMode annotation.
@Retention(AnnotationRetention.SOURCE)
@IntDef(NAVIGATION_MODE_STANDARD, NAVIGATION_MODE_LIST, NAVIGATION_MODE_TABS)
annotation class NavigationMode

// Declare the constants.
const val NAVIGATION_MODE_STANDARD = 0
const val NAVIGATION_MODE_LIST = 1
const val NAVIGATION_MODE_TABS = 2

abstract class ActionBar {

    // Decorate the target methods with the annotation.
    // Attach the annotation.
    @get:NavigationMode
    @setparam:NavigationMode
    abstract var navigationMode: Int

}

Java

import androidx.annotation.IntDef;
//...
public abstract class ActionBar {
    //...
    // Define the list of accepted constants and declare the NavigationMode annotation.
    @Retention(RetentionPolicy.SOURCE)
    @IntDef({NAVIGATION_MODE_STANDARD, NAVIGATION_MODE_LIST, NAVIGATION_MODE_TABS})
    public @interface NavigationMode {}

    // Declare the constants.
    public static final int NAVIGATION_MODE_STANDARD = 0;
    public static final int NAVIGATION_MODE_LIST = 1;
    public static final int NAVIGATION_MODE_TABS = 2;

    // Decorate the target methods with the annotation.
    @NavigationMode
    public abstract int getNavigationMode();

    // Attach the annotation.
    public abstract void setNavigationMode(@NavigationMode int mode);
}

Beim Erstellen dieses Codes wird eine Warnung ausgegeben, wenn der Parameter mode nicht auf eine der definierten Konstanten (NAVIGATION_MODE_STANDARD, NAVIGATION_MODE_LIST oder NAVIGATION_MODE_TABS) verweist.

Kombinieren Sie @IntDef und @IntRange, um anzugeben, dass eine Ganzzahl entweder eine bestimmte Gruppe von Konstanten oder ein Wert innerhalb eines Bereichs sein kann.

Kombination von Konstanten mit Flags aktivieren

Wenn Nutzer die zulässigen Konstanten mit einem Flag kombinieren können (z. B. |, &, ^ usw.), können Sie eine Anmerkung mit einem flag-Attribut definieren, um zu prüfen, ob ein Parameter oder Rückgabewert auf ein gültiges Muster verweist.

Im folgenden Beispiel wird die DisplayOptions-Anmerkung mit einer Liste gültiger DISPLAY_-Konstanten erstellt:

Kotlin

import androidx.annotation.IntDef
...

@IntDef(flag = true, value = [
    DISPLAY_USE_LOGO,
    DISPLAY_SHOW_HOME,
    DISPLAY_HOME_AS_UP,
    DISPLAY_SHOW_TITLE,
    DISPLAY_SHOW_CUSTOM
])
@Retention(AnnotationRetention.SOURCE)
annotation class DisplayOptions
...

Java

import androidx.annotation.IntDef;
...

@IntDef(flag=true, value={
        DISPLAY_USE_LOGO,
        DISPLAY_SHOW_HOME,
        DISPLAY_HOME_AS_UP,
        DISPLAY_SHOW_TITLE,
        DISPLAY_SHOW_CUSTOM
})
@Retention(RetentionPolicy.SOURCE)
public @interface DisplayOptions {}

...

Wenn Sie Code mit einem Anmerkungsflag erstellen, wird eine Warnung ausgegeben, wenn der dekorierte Parameter oder Rückgabewert nicht auf ein gültiges Muster verweist.

Anmerkung beibehalten

Die @Keep-Anmerkung sorgt dafür, dass eine annotierte Klasse oder Methode nicht entfernt wird, wenn der Code zur Buildzeit minimiert wird. Diese Anmerkung wird in der Regel Methoden und Klassen hinzugefügt, auf die über Reflection zugegriffen wird, um zu verhindern, dass der Compiler den Code als nicht verwendet behandelt.

Achtung : Die Klassen und Methoden, die Sie mit @Keep annotieren, werden immer im APK Ihrer App angezeigt, auch wenn Sie in der Logik Ihrer App nie auf diese Klassen und Methoden verweisen.

Um die Größe Ihrer App klein zu halten, sollten Sie überlegen, ob es notwendig ist, jede @Keep-Anmerkung in Ihrer App beizubehalten. Wenn Sie Reflection verwenden, um auf eine annotierte Klasse oder Methode zuzugreifen, verwenden Sie in Ihren ProGuard-Regeln eine -if-Bedingung, in der Sie die Klasse angeben, die die Reflection-Aufrufe ausführt.

Weitere Informationen zum Minimieren von Code und zum Angeben von Code, der nicht entfernt werden soll, finden Sie unter App verkleinern, verschleieren und optimieren.

Anmerkungen zur Sichtbarkeit von Code

Mit den folgenden Anmerkungen können Sie die Sichtbarkeit bestimmter Codeabschnitte wie Methoden, Klassen, Felder oder Pakete angeben.

Code für Tests sichtbar machen

Die Anmerkung @VisibleForTesting gibt an, dass eine kommentierte Methode besser sichtbar ist als normalerweise erforderlich, um die Methode testbar zu machen. Diese Anmerkung hat ein optionales otherwise-Argument, mit dem Sie angeben können, wie die Sichtbarkeit der Methode wäre, wenn sie nicht für Tests sichtbar gemacht werden müsste. Lint verwendet das Argument otherwise, um die gewünschte Sichtbarkeit zu erzwingen.

Im folgenden Beispiel ist myMethod() normalerweise private, für Tests jedoch package-private. Bei der Kennzeichnung VisibleForTesting.PRIVATE zeigt lint eine Meldung an, wenn diese Methode außerhalb des durch den private-Zugriff zulässigen Kontexts aufgerufen wird, z. B. aus einer anderen Kompilierungseinheit.

Kotlin

@VisibleForTesting(otherwise = VisibleForTesting.PRIVATE)
fun myMethod() {
    ...
}

Java

@VisibleForTesting(otherwise = VisibleForTesting.PRIVATE)
void myMethod() { ... }

Sie können auch @VisibleForTesting(otherwise = VisibleForTesting.NONE) angeben, um anzugeben, dass eine Methode nur zu Testzwecken vorhanden ist. Dieses Formular entspricht der Verwendung von @RestrictTo(TESTS). Beide führen dieselbe Lint-Prüfung durch.

API einschränken

Die Anmerkung @RestrictTo gibt an, dass der Zugriff auf die annotierte API (Paket, Klasse oder Methode) eingeschränkt ist.

Unterklassen

Verwenden Sie das Anmerkungsformular @RestrictTo(RestrictTo.Scope.SUBCLASSES), um den API-Zugriff auf Unterklassen zu beschränken.

Nur Klassen, die die annotierte Klasse erweitern, können auf diese API zugreifen. Der Java-Modifikator protected ist nicht restriktiv genug, da er den Zugriff von nicht zugehörigen Klassen innerhalb desselben Pakets zulässt. Es gibt auch Fälle, in denen Sie eine Methode public für zukünftige Flexibilität beibehalten möchten, da Sie eine zuvor protected und überschriebene Methode public nie wieder protected machen können, aber einen Hinweis darauf geben möchten, dass die Klasse nur für die Verwendung innerhalb der Klasse oder von Unterklassen vorgesehen ist.

Bibliotheken

Verwenden Sie das Anmerkungsformular @RestrictTo(RestrictTo.Scope.LIBRARY_GROUP_PREFIX), um den API-Zugriff auf Ihre Bibliotheken einzuschränken.

Nur Ihr Bibliothekcode kann auf die annotierte API zugreifen. So können Sie Ihren Code nicht nur in einer beliebigen Pakethierarchie organisieren, sondern auch für eine Gruppe ähnlicher Bibliotheken freigeben. Diese Option ist bereits für Jetpack-Bibliotheken verfügbar, die viel Implementierungscode enthalten, der nicht für die externe Verwendung gedacht ist, aber public sein muss, um ihn für die verschiedenen ergänzenden Jetpack-Bibliotheken freizugeben.

Testen

Verwenden Sie das Anmerkungsformular @RestrictTo(RestrictTo.Scope.TESTS), um zu verhindern, dass andere Entwickler auf Ihre Test-APIs zugreifen.

Nur Testcode kann auf die annotierte API zugreifen. So wird verhindert, dass andere Entwickler APIs für die Entwicklung verwenden, die Sie nur zu Testzwecken verwenden möchten.