Mit Tools zur Code-Inspektion wie lint können Sie Probleme finden und Ihren Code verbessern. Solche Tools können jedoch nur begrenzt 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 eine String-Ressource angegeben haben, wo Sie eine Farbe hätten angeben sollen. Das bedeutet, dass Ihre App möglicherweise nicht richtig gerendert wird oder gar nicht ausgeführt werden kann, selbst wenn Sie die Code-Inspektion verwenden.
Mit Annotationen können Sie Tools zur Code-Inspektion 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 Tools zur Code-Inspektion können Annotationen Ihnen helfen, Probleme wie NullPointerExceptions und Konflikte bei Ressourcentypen zu erkennen.
Android unterstützt eine Vielzahl von Annotationen über die Jetpack Annotations Library.
Sie können über das Paket androidx.annotation auf die Bibliothek zugreifen.
Hinweis:Wenn ein Modul eine Abhängigkeit von einem Annotationsprozessor hat, 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 Annotationen in Ihrem Projekt aktivieren möchten, fügen Sie die Abhängigkeit androidx.annotation:annotation zu Ihrer Bibliothek oder App hinzu. Alle von Ihnen hinzugefügten Annotationen werden geprüft, wenn Sie eine Code-Inspektion oder eine lint-Aufgabe ausführen.
Abhängigkeit von der Jetpack Annotations-Bibliothek hinzufügen
Die Jetpack Annotations-Bibliothek wird im Maven-Repository von Google veröffentlicht.
Wenn Sie die Jetpack Annotations-Bibliothek Ihrem Projekt hinzufügen möchten, fügen Sie die folgende Zeile in den dependencies-Block Ihrer build.gradle- oder build.gradle.kts-Datei ein:
Kotlin
dependencies { implementation("androidx.annotation:annotation:1.11.0") }
Groovy
dependencies { implementation 'androidx.annotation:annotation:1.11.0' }
Wenn Sie Annotationen in Ihrem eigenen Bibliotheksmodul verwenden, werden die Annotationen als Teil des Android-Archiv-Artefakts (AAR) im XML-Format in die Datei annotations.zip aufgenommen. Durch das Hinzufügen der androidx.annotation-Abhängigkeit wird keine Abhängigkeit für nachgelagerte 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 Annotations-Bibliothek abhängen, hast du möglicherweise bereits Zugriff auf die Annotationen.
Eine vollständige Liste der Annotationen im Jetpack-Repository finden Sie in der Referenz zur Jetpack-Annotationsbibliothek. Alternativ können Sie die Funktion zur automatischen Vervollständigung verwenden, um die verfügbaren Optionen für die Anweisung import androidx.annotation. aufzurufen.
Code-Inspektionen ausführen
Wenn Sie eine Code-Inspektion in Android Studio starten möchten, die die Validierung von Annotationen und die automatische Lint-Prüfung umfasst, wählen Sie im Menü Analyze> Inspect Code aus. In Android Studio werden Konfliktmeldungen angezeigt, um auf potenzielle Probleme hinzuweisen, bei denen Ihr Code mit Annotationen in Konflikt steht, und um mögliche Lösungen vorzuschlagen.
Sie können Annotationen auch erzwingen, indem Sie die Aufgabe lint über die Befehlszeile ausführen. Dies kann zwar nützlich sein, um Probleme mit einem Continuous-Integration-Server zu kennzeichnen, aber die Aufgabe lint erzwingt keine Nullness-Annotationen (im folgenden Abschnitt beschrieben). Dies 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 generieren zwar Warnungen, diese verhindern jedoch nicht, dass Ihre App kompiliert wird.
Nullness-Annotationen
Nullness-Annotationen können in Java-Code nützlich sein, um festzulegen, ob Werte null sein können. In Kotlin-Code sind sie weniger nützlich, da Kotlin integrierte Regeln für die Null-Zulässigkeit hat, die zur Kompilierungszeit erzwungen werden.Fügen Sie die Annotationen @Nullable und @NonNull hinzu, um zu prüfen, ob eine bestimmte Variable, ein bestimmter Parameter oder ein bestimmter Rückgabewert null ist. Die Annotation @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, die einen Nullwert enthält, als Parameter an eine Methode mit der Annotation @NonNull übergeben wird, die an diesen Parameter angehängt ist, wird beim Erstellen des Codes eine Warnung generiert, die auf einen Konflikt mit einem Nicht-Nullwert 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 Nullness-Warnung generiert. 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 Null-Zulässigkeit in Aktion. Im Kotlin-Beispielcode wird die Annotation @NonNull nicht verwendet, da sie automatisch dem generierten Bytecode hinzugefügt wird, wenn ein Typ angegeben wird, der nicht null sein darf. Im Java-Beispiel wird die Annotation @NonNull 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 Methode onCreateView() 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) { ... } ...
Nullability-Analyse
Android Studio unterstützt die Ausführung einer Null-Zulässigkeitsanalyse, um Null-Zulässigkeitsanmerkungen automatisch abzuleiten und in Ihren Code einzufügen. Bei einer Null-Zulässigkeitsanalyse werden die Verträge in den Methodenhierarchien Ihres Codes gescannt, um Folgendes zu erkennen:
- Aufrufen von Methoden, die null zurückgeben können.
- Methoden, die nicht null 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 Analyse fügt dann automatisch die entsprechenden Null-Annotationen an den erkannten Stellen ein.
Wenn Sie in Android Studio eine Null-Zulässigkeitsanalyse ausführen möchten, wählen Sie Analyze > Infer Nullity aus. Android Studio fügt die Android-Annotationen @Nullable und @NonNull an den erkannten Stellen in Ihrem Code ein. Nach dem Ausführen einer Null-Analyse empfiehlt es sich, die eingefügten Annotationen zu überprüfen.
Hinweis:Wenn Sie Nullness-Annotationen hinzufügen, schlägt die automatische Vervollständigung möglicherweise die IntelliJ-Annotationen
@Nullable und @NotNull anstelle der Android-Null-Annotationen vor und importiert die entsprechende Bibliothek automatisch. Die Lint-Prüfung von Android Studio sucht jedoch nur nach den Android-Null-Anmerkungen. Prüfen Sie beim Verifizieren Ihrer Annotationen, ob Ihr Projekt die Android-Null-Annotationen verwendet, damit die Lint-Prüfung Sie bei der Code-Inspektion ordnungsgemäß benachrichtigen kann.
Ressourcenannotationen
Die Validierung von Ressourcentypen kann nützlich sein, da Android-Verweise auf Ressourcen, z. B. drawable- und string-Ressourcen, als Ganzzahlen übergeben werden.
Code, der erwartet, dass ein Parameter auf einen bestimmten Ressourcentyp verweist, z. B. auf einen String, kann an den erwarteten Referenztyp int übergeben werden, verweist aber tatsächlich auf einen anderen Ressourcentyp, z. B. auf eine R.string-Ressource.
Fügen Sie beispielsweise @StringRes-Annotationen hinzu, um zu prüfen, ob ein Ressourcenparameter einen R.string-Verweis enthält, wie hier gezeigt:
Kotlin
abstract fun setTitle(@StringRes resId: Int)
Java
public abstract void setTitle(@StringRes int resId)
Während der Codeprüfung wird durch die Annotation eine Warnung generiert, wenn im Parameter kein R.string-Verweis übergeben wird.
Annotationen für andere Ressourcentypen wie @DrawableRes, @DimenRes, @ColorRes und @InterpolatorRes können im selben Annotationsformat 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 mehr als eine Ressourcentyp-Annotation angeben. Verwenden Sie @AnyRes, um anzugeben, dass der annotierte Parameter ein beliebiger Typ von R-Ressource sein kann.
Sie können zwar mit @ColorRes angeben, dass ein Parameter eine Farbressource sein soll, aber eine Farb-Ganzzahl (im Format RRGGBB oder AARRGGBB) wird nicht als Farbressource erkannt. Verwenden Sie stattdessen die Annotation @ColorInt, um anzugeben, dass ein Parameter eine Farb-Ganzzahl sein muss. Die Build-Tools kennzeichnen fehlerhaften Code, der eine Farbressourcen-ID wie android.R.color.black anstelle einer Farb-Ganzzahl an annotierte Methoden übergibt.
Thread-Annotationen
Mit Thread-Annotationen wird geprüft, ob eine Methode von einem bestimmten Thread-Typ aufgerufen wird. Die folgenden Thread-Anmerkungen werden unterstützt:
Die Build-Tools behandeln die Annotationen @MainThread und @UiThread als austauschbar, sodass Sie @UiThread-Methoden aus @MainThread-Methoden aufrufen können und umgekehrt. Bei System-Apps mit mehreren Ansichten in verschiedenen Threads kann sich der 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 Threading-Anforderung haben, können Sie der Klasse eine einzelne Thread-Annotation hinzufügen, um zu prüfen, ob alle Methoden in der Klasse vom selben Thread-Typ aufgerufen werden.
Eine häufige Verwendung von Thread-Annotationen besteht darin, zu prüfen, ob mit @WorkerThread annotierte Methoden oder Klassen nur von einem geeigneten Hintergrundthread aufgerufen werden.
Anmerkungen zu Wertbeschränkungen
Verwenden Sie die Annotationen @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 wahrscheinlich den Bereich falsch angeben.
Mit der Annotation @IntRange wird geprüft, ob ein Ganzzahl- oder Long-Parameterwert innerhalb eines angegebenen Bereichs liegt. Im folgenden Beispiel wird angegeben, dass der Parameter alpha einen Ganzzahlwert von 0 bis 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 Annotation @FloatRange wird geprüft, ob ein Float- oder Double-Parameterwert innerhalb eines angegebenen Bereichs von Gleitkommawerten liegt. Im folgenden Beispiel wird angegeben, dass der Parameter alpha einen Gleitkommawert von 0,0 bis 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 Annotation @Size wird die Größe einer Sammlung oder eines Arrays oder die Länge eines Strings geprüft. Mit der Annotation @Size können die folgenden Eigenschaften überprüft werden:
- Mindestgröße, z. B.
@Size(min=2) - Maximale Größe, z. B.
@Size(max=2) - Genaue Größe, z. B.
@Size(2) - Eine Zahl, von der die Größe ein Vielfaches sein muss, z. B.
@Size(multiple=2)
Beispiel: Mit @Size(min=1) wird geprüft, ob eine Sammlung nicht leer ist, und mit @Size(3) wird geprüft, ob ein Array genau drei Werte enthält.
Das folgende Beispiel zeigt, 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); }
Berechtigungsannotationen
Verwenden Sie die Annotation @RequiresPermission, um die Berechtigungen des Aufrufers einer Methode zu prüfen. Wenn Sie eine einzelne Berechtigung aus einer Liste gültiger Berechtigungen prüfen möchten, verwenden Sie das Attribut anyOf. Verwenden Sie das Attribut allOf, um eine Reihe von Berechtigungen zu prüfen. Im folgenden Beispiel wird die Methode setWallpaper() annotiert, um anzugeben, 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 Methode copyImageFile() sowohl Lesezugriff auf den externen Speicher als auch Lesezugriff auf die Standortmetadaten im kopierten Image 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) { //... }
Wenn Sie Berechtigungen für Intents festlegen möchten, platzieren Sie die Berechtigungsanforderung im Stringfeld, 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 Contentanbieter separate Berechtigungen für den Lese- und Schreibzugriff erforderlich sind, verpacken Sie jede Berechtigungsanforderung in eine @RequiresPermission.Read- oder @RequiresPermission.Write-Annotation:
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 von dem spezifischen Wert abhängt, der für den Parameter einer Methode angegeben wird, verwenden Sie @RequiresPermission für den Parameter selbst, ohne die spezifischen Berechtigungen aufzulisten.
Die Methode startActivity(Intent) verwendet beispielsweise eine indirekte Berechtigung für den Intent, der 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-Annotationen enthält. Anschließend werden alle vorhandenen Annotationen aus dem Parameter für die Methode selbst erzwungen. Im Beispiel startActivity(Intent) führen Annotationen in der Klasse Intent zu den resultierenden Warnungen bei ungültiger Verwendung von startActivity(Intent), wenn ein Intent ohne die entsprechenden Berechtigungen an die Methode übergeben wird, wie in Abbildung 1 dargestellt.
Abbildung 1. Die Warnung, die von einer Annotation für indirekte Berechtigungen für die Methode startActivity(Intent) generiert wurde.
Die Build-Tools generieren die Warnung für startActivity(Intent) aus der Annotation für den entsprechenden Intent-Aktionsnamen in der Klasse Intent:
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 durch @RequiresPermission.Read oder @RequiresPermission.Write ersetzen, wenn Sie den Parameter einer Methode annotieren. Für indirekte Berechtigungen sollte @RequiresPermission jedoch nicht in Verbindung mit den Annotationen für Lese- oder Schreibberechtigungen verwendet werden.
Anmerkungen zum Rückgabewert
Mit der Annotation @CheckResult können Sie prüfen, ob das Ergebnis oder der Rückgabewert einer Methode tatsächlich verwendet wird. Anstatt jede Methode, die nicht „void“ ist, mit @CheckResult zu annotieren, fügen Sie die Annotation hinzu, um die Ergebnisse potenziell verwirrender Methoden zu verdeutlichen.
Beispielsweise denken neue Java-Entwickler oft fälschlicherweise, dass <String>.trim() Leerzeichen aus dem ursprünglichen String entfernt. Wenn Sie die Methode mit @CheckResult annotieren, werden Verwendungen von <String>.trim() gekennzeichnet, bei denen der Aufrufer nichts mit dem Rückgabewert der Methode macht.
Im folgenden Beispiel wird die Methode checkPermissions() annotiert, um zu prüfen, ob der Rückgabewert der Methode tatsächlich referenziert wird. Außerdem wird die Methode enforcePermission() als Methode genannt, die dem Entwickler als Ersatz vorgeschlagen werden soll:
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-Annotationen
Verwenden Sie die Annotation @CallSuper, um zu prüfen, ob eine überschreibende Methode die Super-Implementierung der Methode aufruft.
Im folgenden Beispiel wird die Methode onCreate() annotiert, um sicherzustellen, dass alle überschreibenden Methodenimplementierungen super.onCreate() aufrufen:
Kotlin
@CallSuper override fun onCreate(savedInstanceState: Bundle?) { }
Java
@CallSuper protected void onCreate(Bundle savedInstanceState) { }
Typedef-Annotationen
Mit Typedef-Anmerkungen wird geprüft, ob ein bestimmter Parameter, Rückgabewert oder ein bestimmtes Feld auf eine bestimmte Gruppe von Konstanten verweist. Außerdem ermöglichen sie die Codevervollständigung, um die zulässigen Konstanten automatisch anzubieten.
Verwenden Sie die Annotationen @IntDef und @StringDef, um Aufzählungsannotationen von Ganzzahl- und String-Sets zu erstellen, um andere Arten von Codereferenzen zu validieren.
Typedef-Annotationen verwenden @interface, um den neuen Aufzählungsannotationstyp zu deklarieren.
Die Annotationen @IntDef und @StringDef sowie @Retention annotieren die neue Annotation und sind erforderlich, um den Aufzählungstyp zu definieren. Die Annotation @Retention(RetentionPolicy.SOURCE) weist den Compiler an, die aufgezählten Annotationsdaten nicht in der Datei .class zu speichern.
Im folgenden Beispiel wird gezeigt, wie Sie eine Annotation erstellen, 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); }
Wenn Sie diesen Code erstellen, wird eine Warnung generiert, 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 ein bestimmter Satz 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 (z. B. |, &, ^ usw.) kombinieren können, können Sie eine Annotation 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 Annotation DisplayOptions 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 Annotations-Flag erstellen, wird eine Warnung generiert, wenn der dekorierte Parameter oder Rückgabewert nicht auf ein gültiges Muster verweist.
Anmerkung beibehalten
Die Annotation @Keep sorgt dafür, dass eine annotierte Klasse oder Methode nicht entfernt wird, wenn der Code beim Erstellen minimiert wird. Diese Annotation wird normalerweise Methoden und Klassen hinzugefügt, auf die über Reflexion zugegriffen wird, um zu verhindern, dass der Compiler den Code als ungenutzt 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.
Damit die App klein bleibt, sollten Sie überlegen, ob es notwendig ist, jede @Keep-Annotation in Ihrer App beizubehalten. Wenn Sie Reflexion verwenden, um auf eine annotierte Klasse oder Methode zuzugreifen, verwenden Sie in Ihren ProGuard-Regeln eine
-if-Bedingung und geben Sie die Klasse an, die die Reflexionsaufrufe ausführt.
Weitere Informationen dazu, wie Sie Ihren Code minimieren und angeben, welcher Code nicht entfernt werden soll, finden Sie unter App komprimieren, verschleiern und optimieren.
Anmerkungen zur Codesichtbarkeit
Verwenden Sie die folgenden Annotationen, um die Sichtbarkeit bestimmter Codeabschnitte wie Methoden, Klassen, Felder oder Pakete anzugeben.
Code für Tests sichtbar machen
Die Annotation @VisibleForTesting gibt an, dass eine annotierte Methode sichtbarer ist, als normalerweise erforderlich, um die Methode testbar zu machen. Diese Annotation hat ein optionales otherwise-Argument, mit dem Sie die Sichtbarkeit der Methode festlegen können, wenn sie nicht für Tests sichtbar sein muss. Lint verwendet das Argument otherwise, um die gewünschte Sichtbarkeit zu erzwingen.
Im folgenden Beispiel ist myMethod() normalerweise private, für Tests aber package-private. Mit der Bezeichnung VisibleForTesting.PRIVATE zeigt Lint eine Meldung an, wenn diese Methode von außerhalb des durch den private-Zugriff zulässigen Kontexts aufgerufen wird, z. B. von 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 existiert. Dieses Formular entspricht der Verwendung von @RestrictTo(TESTS). Beide führen dieselbe Lint-Prüfung durch.
API einschränken
Die Annotation @RestrictTo gibt an, dass der Zugriff auf die annotierte API (Paket, Klasse oder Methode) wie folgt eingeschränkt ist:
Abgeleitete Klassen
Verwenden Sie das Annotationsformular @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 verwandten Klassen innerhalb desselben Pakets zulässt. Es gibt auch Fälle, in denen Sie eine Methode public für zukünftige Flexibilität belassen möchten, da Sie eine zuvor protected und überschriebene Methode nie public machen können, aber Sie möchten einen Hinweis geben, dass die Klasse nur für die Verwendung innerhalb der Klasse oder von Unterklassen vorgesehen ist.
Bibliotheken
Verwenden Sie das Annotationsformular @RestrictTo(RestrictTo.Scope.LIBRARY_GROUP_PREFIX), um den API-Zugriff nur auf Ihre Bibliotheken zu beschränken.
Nur Ihr Bibliothekscode 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 verwandter Bibliotheken freigeben. Diese Option ist bereits für die Jetpack-Bibliotheken verfügbar, die viel Implementierungscode enthalten, der nicht für die externe Verwendung bestimmt ist, aber public sein muss, um ihn in den verschiedenen ergänzenden Jetpack-Bibliotheken freizugeben.
Test
Verwenden Sie das Annotationsformular @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 vorgesehen haben.