Codeprüfungstools wie Lint können Ihnen helfen, Probleme zu finden und Ihren Code zu verbessern, aber Prüftools können nur so viel ableiten. Android-Ressourcen-IDs verwenden beispielsweise ein int
, um Strings, Grafiken, Farben und andere Ressourcentypen zu identifizieren, sodass Prüftools nicht erkennen können, ob Sie eine Stringressource angegeben haben, für die Sie eigentlich eine Farbe festlegen sollten. Das bedeutet, dass Ihre App möglicherweise falsch gerendert oder überhaupt nicht ausgeführt wird, selbst wenn Sie die Codeprüfung verwenden.
Mit Annotationen können Sie Tools für die Codeprüfung wie Lint Hinweise zur Verfügung stellen, um diese subtileren Codeprobleme zu erkennen. Anmerkungen werden als Metadaten-Tags hinzugefügt, die Sie an Variablen, Parameter und Rückgabewerte anhängen, um Rückgabewerte von Methoden, übergebene Parameter, lokale Variablen und Felder zu untersuchen. In Verbindung mit Code-Inspektionstools können Annotationen dabei helfen, Probleme wie Nullzeigerausnahmen und Konflikte bei Ressourcentypen zu erkennen.
Android unterstützt eine Vielzahl von Anmerkungen ü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 zum Hinzufügen dieser Abhängigkeit entweder die Abhängigkeitskonfiguration kapt
oder ksp
für Kotlin oder die Abhängigkeitskonfiguration annotationProcessor
für Java verwenden.
Anmerkungen zum Projekt hinzufügen
Um Annotationen in Ihrem Projekt zu aktivieren, fügen Sie die androidx.annotation:annotation
-Abhängigkeit zu Ihrer Bibliothek oder App hinzu. Alle hinzugefügten Annotationen werden geprüft, wenn Sie eine Codeüberprüfung oder eine lint
-Aufgabe ausführen.
Abhängigkeit der Jetpack-Anmerkungsbibliothek hinzufügen
Die Jetpack-Annotationsbibliothek wird im Maven-Repository von Google veröffentlicht.
Um Ihrem Projekt die Jetpack-Anmerkungsbibliothek hinzuzufügen, fügen Sie die folgende Zeile in den dependencies
-Block der build.gradle
- oder build.gradle.kts
-Datei ein:
Kotlin
dependencies { implementation("androidx.annotation:annotation:1.7.1") }
Groovig
dependencies { implementation 'androidx.annotation:annotation:1.7.1' }
Wenn Sie Annotationen in Ihrem eigenen Bibliotheksmodul verwenden, sind diese in der Datei annotations.zip
als Teil des Android Archive-Artefakts (AAR) im XML-Format enthalten. Durch das Hinzufügen der Abhängigkeit androidx.annotation
entsteht keine Abhängigkeit für nachgelagerte Nutzer Ihrer Bibliothek.
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 Annotationsbibliothek abhängen, haben Sie möglicherweise bereits Zugriff auf die Annotationen.
Eine vollständige Liste der Annotationen im Jetpack-Repository finden Sie entweder in der Referenz zur Jetpack-Annotationsbibliothek oder verwenden Sie die Funktion zur automatischen Vervollständigung, um die verfügbaren Optionen für die import androidx.annotation.
-Anweisung aufzurufen.
Codeprüfungen ausführen
Wählen Sie im Menü Analysieren > Code untersuchen aus, um in Android Studio eine Codeprüfung zu starten, die Annotationen und automatische Lint-Prüfung umfasst. 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 Annotationen auch erzwingen, indem Sie die Aufgabe lint
über die Befehlszeile ausführen. Dies kann nützlich sein, wenn Sie Probleme mit einem Continuous-Integration-Server melden. Die Aufgabe lint
erzwingt jedoch keine Annotationen für Nullwerte (wird 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.
Obwohl Annotationskonflikte Warnungen generieren, verhindern diese Warnungen nicht, dass Ihre Anwendung kompiliert wird.
Annotationen von Null-NULL-Werten
Nullness-Annotationen können in Java-Code nützlich sein, um zu erzwingen, ob Werte null sein dürfen. Sie sind in Kotlin-Code weniger nützlich, da Kotlin Regeln für die Null-Zulässigkeit eingebaut hat, die beim Kompilieren erzwungen werden.Fügen Sie die Annotationen @Nullable
und @NonNull
hinzu, um die NULL-Werte einer bestimmten Variablen, eines Parameters oder eines Rückgabewerts zu prüfen. Die Annotation @Nullable
gibt eine Variable, einen Parameter oder einen Rückgabewert an, die bzw. 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 Nicht-Null-Konflikt hinweist. Wenn außerdem versucht wird, auf das Ergebnis einer mit @Nullable
gekennzeichneten Methode zu verweisen, ohne vorher zu prüfen, ob das Ergebnis null ist, wird eine Null-Warnung ausgelöst. Verwenden Sie @Nullable
nur dann für den Rückgabewert einer Methode, wenn bei jeder Verwendung der Methode explizit eine Nullprüfung durchgeführt werden muss.
Das folgende Beispiel zeigt die Null-Zulässigkeit in Aktion. Im Kotlin-Beispielcode wird die Annotation @NonNull
nicht genutzt, da sie dem generierten Bytecode automatisch hinzugefügt wird, wenn ein Typ angegeben wird, der keine Nullwerte zulässt. Im Java-Beispiel wird mithilfe der Annotation @NonNull
für die Parameter context
und attrs
geprüft, 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) { ... } ...
Analyse der Null-Zulässigkeit
Android Studio unterstützt die Durchführung einer Null-Zulässigkeitsanalyse, um automatisch Annotationen abzuleiten und in Ihren Code einzufügen. Eine Null-Zulässigkeitsanalyse scannt die Verträge in den Methodenhierarchien in Ihrem Code, um Folgendes zu erkennen:
- Aufrufmethoden, die null zurückgeben können.
- Methoden, die nicht null zurückgeben sollen.
- Variablen wie Felder, lokale Variablen und Parameter, die null sein können.
- Variablen wie Felder, lokale Variablen und Parameter, die keinen Nullwert enthalten dürfen.
Die Analyse fügt dann automatisch die entsprechenden Null-Annotationen an den erkannten Orten ein.
Wählen Sie zum Ausführen einer Null-Zulässigkeitsanalyse in Android Studio Analysieren > Nullwerte ableiten aus. Android Studio fügt die Android-Anmerkungen @Nullable
und @NonNull
in erkannten Positionen in Ihrem Code ein. Nach dem Ausführen einer Nullanalyse empfiehlt es sich, die injizierten Annotationen zu überprüfen.
Hinweis:Beim Hinzufügen von Null-Annotationen schlägt die automatische Vervollständigung möglicherweise die IntelliJ-Anmerkungen
@Nullable
und @NotNull
anstelle der Null-Annotationen von Android vor und importiert die entsprechende Bibliothek automatisch. Die Lint-Prüfung von Android Studio sucht jedoch nur nach Null-Annotationen von Android. Achten Sie beim Überprüfen der Annotationen darauf, dass Ihr Projekt die Null-Annotationen von Android verwendet, damit Sie während der Codeprüfung von der Lint-Prüfung ordnungsgemäß benachrichtigt werden können.
Ressourcenanmerkungen
Das Prüfen von Ressourcentypen kann nützlich sein, da Android-Verweise auf Ressourcen wie drawable- und string-Ressourcen als Ganzzahlen übergeben werden.
Code, der erwartet, dass ein Parameter auf einen bestimmten Ressourcentyp wie String
verweist, kann an den erwarteten Referenztyp von int
übergeben werden, verweist jedoch auf einen anderen Ressourcentyp wie eine R.string
-Ressource.
Fügen Sie beispielsweise @StringRes
-Annotationen hinzu, um zu prüfen, ob ein Ressourcenparameter wie hier gezeigt einen R.string
-Verweis enthält:
Kotlin
abstract fun setTitle(@StringRes resId: Int)
Java
public abstract void setTitle(@StringRes int resId)
Bei der Codeprüfung generiert die Annotation eine Warnung, wenn im Parameter kein R.string
-Verweis übergeben wird.
Annotationen für andere Ressourcentypen wie @DrawableRes
, @DimenRes
, @ColorRes
und @InterpolatorRes
können mit demselben Annotationsformat hinzugefügt und während der Codeprüfung ausgeführt werden.
Wenn der Parameter mehrere Ressourcentypen unterstützt, können Sie einem Parameter mehrere Ressourcentyp-Annotationen hinzufügen. Mit @AnyRes
geben Sie an, dass der annotierte Parameter ein beliebiger Typ von R
-Ressource sein kann.
Sie können mit @ColorRes
zwar angeben, dass ein Parameter eine Farbressource sein soll, eine Farbganzzahl im Format RRGGBB
oder AARRGGBB
wird jedoch nicht als Farbressource erkannt. Verwenden Sie stattdessen die Annotation @ColorInt
, um anzugeben, dass ein Parameter eine Farbganzzahl sein muss. Die Build-Tools markieren falschen Code, der eine Farbressourcen-ID wie android.R.color.black
anstelle einer Ganzzahl als Farbe an annotierte Methoden übergibt.
Thread-Anmerkungen
Thread-Annotationen prüfen, ob eine Methode von einem bestimmten Thread aufgerufen wird. Die folgenden Thread-Annotationen werden unterstützt:
Die Build-Tools behandeln die @MainThread
- und @UiThread
-Annotationen als austauschbar, sodass Sie @UiThread
-Methoden über @MainThread
-Methoden aufrufen können und umgekehrt. Bei Systemanwendungen mit mehreren Ansichten in verschiedenen Threads kann ein UI-Thread vom Hauptthread jedoch abweichen. Daher sollten Sie Methoden, die der Ansichtshierarchie einer Anwendung zugeordnet sind, mit @UiThread
annotieren und nur Methoden, die dem Lebenszyklus einer Anwendung zugeordnet sind, mit @MainThread
.
Wenn für alle Methoden in einer Klasse die gleiche Threading-Anforderung gilt, können Sie der Klasse eine einzelne Thread-Annotation hinzufügen, um zu überprüfen, ob alle Methoden in der Klasse vom selben Thread-Typ aus aufgerufen werden.
Thread-Annotationen werden häufig verwendet, um zu prüfen, ob mit @WorkerThread
annotierte Methoden oder Klassen nur aus einem geeigneten Hintergrundthread aufgerufen werden.
Annotationen zur Wertbeschränkung
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 einen falschen Bereich liegen.
Die Annotation @IntRange
prüft, ob ein ganzzahliger oder langer Parameterwert innerhalb eines angegebenen Bereichs liegt. Im folgenden Beispiel muss der Parameter alpha
eine Ganzzahl zwischen 0 und 255 enthalten:
Kotlin
fun setAlpha(@IntRange(from = 0, to = 255) alpha: Int) { ... }
Java
public void setAlpha(@IntRange(from=0,to=255) int alpha) { ... }
Die Annotation @FloatRange
prüft, ob ein Gleitkomma- oder Double-Parameterwert innerhalb eines bestimmten Gleitkommabereichs liegt. Im folgenden Beispiel muss der Parameter alpha
eine Gleitkommazahl zwischen 0,0 und 1,0 enthalten:
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) {...}
Die Annotation @Size
prüft die Größe einer Sammlung oder eines Arrays oder die Länge eines Strings. Mit der Annotation @Size
können die folgenden Qualitäten geprüft werden:
- Mindestgröße, z. B.
@Size(min=2)
- Maximalgröße, z. B.
@Size(max=2)
- Genaue Größe, zum Beispiel
@Size(2)
- Eine Zahl, deren Größe ein Vielfaches sein muss, z. B.
@Size(multiple=2)
Beispielsweise prüft @Size(min=1)
, ob eine Sammlung leer ist, und @Size(3)
prüft, ob ein Array genau drei Werte enthält.
Im folgenden Beispiel muss das Array location
mindestens ein Element enthalten:
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); }
Annotationen zu Berechtigungen
Validieren Sie mit der Annotation @RequiresPermission
die Berechtigungen des Aufrufers einer Methode. Mit dem Attribut anyOf
können Sie nach einer einzelnen Berechtigung aus einer Liste gültiger Berechtigungen suchen. Mit dem Attribut allOf
kannst du prüfen, ob eine Reihe von Berechtigungen vorhanden ist. 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;
Für das folgende Beispiel muss der Aufrufer der Methode copyImageFile()
sowohl Lesezugriff auf externen Speicher als auch Lesezugriff auf 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) { //... }
Für Berechtigungen für Intents platzieren Sie die Berechtigungsanforderung in das 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";
Fassen Sie für Berechtigungen für Inhaltsanbieter, die separate Berechtigungen für Lese- und Schreibzugriff benötigen, jede Berechtigungsanforderung in eine @RequiresPermission.Read
- oder @RequiresPermission.Write
-Annotation ein:
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 wurde, 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 erzwingt sie alle vorhandenen Annotationen des Parameters in der Methode selbst. Im Beispiel startActivity(Intent)
verursachen Anmerkungen in der Klasse Intent
die resultierenden Warnungen bei einer ungültigen Verwendung von startActivity(Intent)
, wenn ein Intent ohne die entsprechenden Berechtigungen an die Methode übergeben wird (siehe Abbildung 1).
Die Build-Tools generieren die Warnung für startActivity(Intent)
aus der Annotation zum 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";
Sie können bei Bedarf @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 der Lese- oder Schreibberechtigungen verwendet werden.
Anmerkungen zu Rückgabewerten
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 ohne Leerzeichen mit @CheckResult
zu annotieren, fügen Sie die Annotation hinzu, um die Ergebnisse potenziell verwirrender Methoden zu verdeutlichen.
Neue Java-Entwickler denken beispielsweise oft fälschlicherweise, dass <String>.trim()
Leerzeichen im ursprünglichen String entfernt. Wenn die Methode mit @CheckResult
-Flags annotiert wird, wird <String>.trim()
verwendet, wobei der Aufrufer nichts mit dem Rückgabewert der Methode tut.
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 benannt, die dem Entwickler als Ersatz vorgeschlagen wird:
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 Annotation @CallSuper
können Sie überprüfen, ob eine Überschreibungsmethode die Superimplementierung der Methode aufruft.
Im folgenden Beispiel wird die Methode onCreate()
annotiert, damit bei jeder überschreibenden Methodenimplementierung super.onCreate()
aufgerufen wird:
Kotlin
@CallSuper override fun onCreate(savedInstanceState: Bundle?) { }
Java
@CallSuper protected void onCreate(Bundle savedInstanceState) { }
Typedef-Annotationen
Typedef-Annotationen prüfen, ob ein bestimmter Parameter, Rückgabewert oder ein Feld auf einen bestimmten Satz von Konstanten verweist. Sie ermöglichen auch die Codevervollständigung, um die zulässigen Konstanten automatisch bereitzustellen.
Mit den Annotationen @IntDef
und @StringDef
können Sie Enum-Annotationen mit Ganzzahl- und Stringsätzen erstellen, um andere Arten von Codeverweisen zu validieren.
Typedef-Annotationen verwenden @interface
, um den neuen Enum-Annotationstyp zu deklarieren.
Die Annotationen @IntDef
und @StringDef
annotieren gemeinsam mit @Retention
die neue Annotation und sind erforderlich, um den Aufzählungstyp zu definieren. Die Annotation @Retention(RetentionPolicy.SOURCE)
weist den Compiler an, die Aufzählungsdaten nicht in der Datei .class
zu speichern.
Das folgende Beispiel zeigt die Schritte zum Erstellen einer Annotation, 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 mode
-Parameter 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 kombinieren können (z. B. |
, &
oder ^
), lässt sich eine Annotation mit einem flag
-Attribut definieren. So lässt sich 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 zum Build-Zeitpunkt reduziert wird. Diese Annotation wird in der Regel Methoden und Klassen hinzugefügt, auf die über Reflexion zugegriffen wird. So wird verhindert, 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.
Überlege, ob du jede @Keep
-Annotation in der App beibehalten musst. Wenn du mithilfe der Reflexion auf eine annotierte Klasse oder Methode zugreifen möchtest, verwende eine
-if
-Bedingung in deinen ProGuard-Regeln und lege die Klasse fest, die die Reflexionsaufrufe durchführt.
Weitere Informationen zum Komprimieren von Code und zum Angeben, welcher Code nicht entfernt werden soll, finden Sie unter Anwendung verkleinern, verschleiern und optimieren.
Anmerkungen zur Codesichtbarkeit
Verwenden Sie die folgenden Annotationen, um die Sichtbarkeit bestimmter Teile des Codes festzulegen, z. B. Methoden, Klassen, Felder oder Pakete.
Code zum Testen sichtbar machen
Die Annotation @VisibleForTesting
gibt an, dass eine annotierte Methode besser sichtbar 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 wäre. Lint verwendet das Argument otherwise
, um die gewünschte Sichtbarkeit zu erzwingen.
Im folgenden Beispiel ist myMethod()
normalerweise private
, für Tests ist es aber package-private
. Mit der Kennzeichnung VisibleForTesting.PRIVATE
zeigt Lint eine Meldung an, wenn diese Methode von außerhalb des für den private
-Zugriff erlaubten 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 für Tests vorhanden ist. Dieses Formular ist das gleiche wie das Verwenden 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) eingeschränkt ist:
Abgeleitete Klassen
Verwenden Sie das Annotationsformular @RestrictTo(RestrictTo.Scope.SUBCLASSES)
, um den API-Zugriff auf abgeleitete Klassen 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 in Beziehung stehenden Klassen innerhalb desselben Pakets ermöglicht. Es gibt auch Fälle, in denen Sie für zukünftige Flexibilität die Methode public
beibehalten möchten, da Sie nie eine zuvor protected
und überschriebene Methode public
erstellen können, aber einen Hinweis darauf geben möchten, dass die Klasse nur für Nutzungen innerhalb der Klasse oder von Unterklassen vorgesehen ist.
Bibliotheken
Verwenden Sie das Annotationsformular @RestrictTo(RestrictTo.Scope.LIBRARY_GROUP_PREFIX)
, um den API-Zugriff auf Ihre Bibliotheken zu beschränken.
Nur Ihr Bibliothekscode kann auf die annotierte API zugreifen. Auf diese Weise können Sie Ihren Code nicht nur in einer beliebigen Pakethierarchie organisieren, sondern ihn auch mit einer Gruppe zusammengehöriger Bibliotheken teilen. Diese Option ist bereits für die Jetpack-Bibliotheken mit viel Implementierungscode verfügbar, der nicht für die externe Verwendung bestimmt ist, aber public
sein muss, um ihn mit den verschiedenen komplementären Jetpack-Bibliotheken teilen zu können.
Testen
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 verwenden möchten.