Korzystanie z narzędzi do inspekcji kodu, takich jak lint, może pomóc w wykrywaniu problemów i ulepszaniu kodu, ale narzędzia do inspekcji nie są w stanie wyciągnąć zbyt wielu wniosków. Na przykład identyfikatory zasobów Androida używają wartości int
do identyfikowania ciągów znaków, grafik, kolorów i innych typów zasobów, dzięki czemu narzędzia do inspekcji nie mogą stwierdzić, kiedy zdefiniowano zasób ciągu znaków, a kiedy kolor. W takiej sytuacji aplikacja może się nieprawidłowo renderować lub w ogóle nie uruchomić, nawet jeśli przeprowadzisz kontrolę kodu.
Dzięki adnotacjom możesz przekazywać wskazówki narzędziom do inspekcji kodu, takim jak lint, aby wykrywać te bardziej subtelne problemy z kodem. Adnotacje są dodawane jako tagi metadanych, które możesz dołączać do zmiennych, parametrów i wartości zwracanych, aby sprawdzać wartości zwracane przez metody, przekazywane parametry, zmienne lokalne i pola. W połączeniu z narzędziami do sprawdzania kodu adnotacje mogą pomóc w wykrywaniu problemów, takich jak wyjątki od wskaźników null czy konflikty typów zasobów.
Android obsługuje różne adnotacje z biblioteki adnotacji w Jetpack.
Dostęp do biblioteki możesz uzyskać za pomocą pakietu androidx.annotation
.
Uwaga: jeśli moduł jest zależny od procesora adnotacji, musisz użyć konfiguracji zależności kapt
lub ksp
w przypadku Kotlina albo konfiguracji zależności annotationProcessor
w przypadku Javy, aby dodać tę zależność.
Dodawanie adnotacji do projektu
Aby włączyć adnotacje w projekcie, dodaj zależność androidx.annotation:annotation
do biblioteki lub aplikacji. Dodane adnotacje są sprawdzane podczas inspekcji kodu lub zadania lint
.
Dodaj zależność biblioteki Jetpack Adnotacje
Biblioteka Jetpack Annotations jest publikowana w repozytorium Maven Google.
Aby dodać do projektu bibliotekę Jetpack Anotations, dodaj ten wiersz do bloku dependencies
w pliku build.gradle
lub build.gradle.kts
:
Kotlin
dependencies { implementation("androidx.annotation:annotation:1.9.1") }
Groovy
dependencies { implementation 'androidx.annotation:annotation:1.9.1' }
Jeśli w swoim własnym module biblioteki używasz adnotacji, są one uwzględniane w ramach artefaktu Android Archive (AAR) w formacie XML w pliku annotations.zip
. Dodanie zależności androidx.annotation
nie powoduje uzależnienia od kolejnych użytkowników Twojej biblioteki.
Uwaga: jeśli używasz innych bibliotek Jetpacka, możesz nie musieć dodawać zależności androidx.annotation
. Wiele innych bibliotek Jetpacka bazuje na bibliotece adnotacji, więc możesz już mieć do nich dostęp.
Pełną listę adnotacji znajdujących się w repozytorium Jetpack znajdziesz w dokumentacji biblioteki adnotacji Jetpack. Możesz też skorzystać z funkcji autouzupełniania, aby wyświetlić opcje dostępne dla instrukcji import androidx.annotation.
.
Przeprowadzanie inspekcji kodu
Aby rozpocząć sprawdzanie kodu w Android Studio, które obejmuje sprawdzanie poprawności adnotacji i automatyczne sprawdzanie błędów, w menu kliknij Analizuj > Sprawdzanie kodu. Android Studio wyświetla komunikaty o konflikcie, aby sygnalizować potencjalne problemy, w których Twój kod jest niezgodny z adnotacjami, oraz sugerować możliwe rozwiązania.
Możesz też wymusić adnotacje, uruchamiając zadanie lint
za pomocą wiersza poleceń. Chociaż może to być przydatne do oznaczania problemów z serwerem ciągłej integracji, zadanie lint
nie wymusza adnotacji nullości (opisanych w następnej sekcji); robi to tylko Android Studio. Więcej informacji o włączaniu i uruchamianiu kontroli lint znajdziesz w artykule Ulepszanie kodu za pomocą kontroli lint.
Konflikty adnotacji generują ostrzeżenia, ale nie uniemożliwiają kompilacji aplikacji.
Adnotacje dotyczące wartości NULL
W kodzie Java adnotacje nullości mogą być przydatne do wymuszania, czy wartości mogą być null. W kodzie Kotlina są one mniej przydatne, ponieważ Kotlin ma wbudowane reguły dotyczące możliwości wystąpienia wartości null, które są egzekwowane w czasie kompilacji.Dodaj adnotacje @Nullable
i @NonNull
, aby sprawdzić, czy dana zmienna, parametr lub wartość zwracana jest pusta. Adnotacja @Nullable
wskazuje zmienną, parametr lub wartość zwracaną, która może być pusta.
@NonNull
wskazuje zmienną, parametr lub wartość zwracaną, która nie może być pusta.
Jeśli na przykład zmienna lokalna zawierająca wartość null jest przekazywana jako parametr do metody z dołączoną adnotacją @NonNull
, kompilacja kodu powoduje ostrzeżenie o konflikcie z wartością inną niż null. Próba odwołania się do wyniku metody oznaczonej symbolem @Nullable
bez wcześniejszego sprawdzenia, czy wynik jest pusty, powoduje ostrzeżenie o wartości null. Używaj funkcji @Nullable
do wartości zwracanej przez metodę tylko wtedy, gdy każde użycie metody musi być wyraźnie sprawdzane pod kątem wartości null.
Poniższy przykład pokazuje, jak w praktyce działa dopuszczanie wartości null. Przykładowy kod Kotlina nie korzysta z adnotacji @NonNull
, ponieważ jest ona automatycznie dodawana do wygenerowanego kodu bajtowego, gdy określony jest typ, który nie może być pusty. Przykład w języku Java korzysta z adnotacji @NonNull
w przypadku parametrów context
i attrs
, aby sprawdzić, czy przekazane wartości parametrów nie są puste. Sprawdza też, czy metoda onCreateView()
nie zwraca wartości null:
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) { ... } ...
Analiza wartości null
Android Studio obsługuje przeprowadzanie analizy wartości null w celu automatycznego wnioskowania i wstawiania do kodu adnotacji o braku wartości null. Analiza dopuszczalności wartości null skanuje kontrakty za pomocą hierarchii metod w kodzie, aby wykryć:
- Metody wywołań, które mogą zwracać wartość null.
- Metody, które nie powinny zwracać wartości null.
- Zmienne, takie jak pola, zmienne lokalne i parametry, które mogą mieć wartość null.
- Zmienne, takie jak pola, zmienne lokalne i parametry, które nie mogą zawierać wartości null.
Następnie analiza automatycznie wstawia odpowiednie adnotacje null w wykrytych lokalizacjach.
Aby w Android Studio przeprowadzić analizę wartości null, wybierz Analizuj > Wnioskuj o wartości null. Android Studio wstawia adnotacje Androida @Nullable
i @NonNull
w wykrytych lokalizacjach w Twoim kodzie. Po przeprowadzeniu analizy pustych wartości warto zweryfikować wstrzyknięte adnotacje.
Uwaga: podczas dodawania adnotacji nullości autouzupełnianie może sugerować adnotacje IntelliJ
@Nullable
i
@NotNull
zamiast adnotacji nullości na Androida. Może też automatycznie zaimportować odpowiednią bibliotekę. Sprawdzacz lint w Android Studio sprawdza jednak tylko adnotacje null na Androida. Podczas sprawdzania adnotacji sprawdź, czy Twój projekt używa adnotacji null na Androida, aby sprawdzacz lint mógł odpowiednio poinformować Cię o błędach podczas inspekcji kodu.
Adnotacje zasobów
Walidowanie typów zasobów może być przydatne, ponieważ odwołania do zasobów w Androidzie, takich jak zasoby drawable i string, są przekazywane jako liczby całkowite.
Kod, który oczekuje, że parametr odwołuje się do określonego typu zasobu, np. String
, może zostać przekazany do oczekiwanego typu odwołania int
, ale tak naprawdę odwołuje się do innego typu zasobu, np. zasobu R.string
.
Na przykład dodaj adnotacje @StringRes
, aby sprawdzić, czy parametr zasobu zawiera odwołanie R.string
, jak pokazano tutaj:
Kotlin
abstract fun setTitle(@StringRes resId: Int)
Java
public abstract void setTitle(@StringRes int resId)
Podczas sprawdzania kodu adnotacja generuje ostrzeżenie, jeśli w parametrze nie jest przekazywane odwołanie R.string
.
Adnotacje do innych typów zasobów, takich jak @DrawableRes
, @DimenRes
, @ColorRes
i @InterpolatorRes
, można dodawać za pomocą tego samego formatu i uruchamiać je podczas inspekcji kodu.
Jeśli Twój parametr obsługuje wiele typów zasobów, możesz umieścić w nim więcej niż 1 adnotację typu zasobu. Użyj @AnyRes
, aby wskazać, że adnotowany parametr może być dowolnym typem zasobu R
.
Chociaż możesz użyć atrybutu @ColorRes
, aby określić, że parametr powinien być zasobem koloru, liczba całkowita koloru (w formacie RRGGBB
lub AARRGGBB
) nie jest rozpoznawana jako zasób koloru. Zamiast tego użyj adnotacji @ColorInt
, aby wskazać, że parametr musi być liczbą całkowitą koloru. Narzędzia do kompilacji będą oznaczać nieprawidłowy kod, który przekazuje do metody opatrzonej adnotacjami identyfikator zasobu koloru, np. android.R.color.black
, zamiast koloru w postaci liczby całkowitej.
Adnotacje wątków
Adnotacje wątku sprawdzają, czy metoda jest wywoływana z określonego typu wątku. Obsługiwane są te adnotacje wątku:
Narzędzia do tworzenia traktują adnotacje @MainThread
i @UiThread
jako wymienne, więc możesz wywoływać metody @UiThread
z metod @MainThread
i odwrotnie. W przypadku aplikacji systemowych z wieloma widokami w różnych wątkach może się jednak zdarzyć, że wątek interfejsu użytkownika będzie inny niż główny wątek. Dlatego metody powiązane z hierarchią widoku aplikacji należy opatrzyć adnotacją @UiThread
, a metody powiązane z cyklem życia aplikacji – adnotacją @MainThread
.
Jeśli wszystkie metody w klasie mają te same wymagania dotyczące wątków, możesz dodać do klasy pojedynczą adnotację wątku, aby sprawdzić, czy wszystkie metody w klasie są wywoływane z tego samego typu wątku.
Typowym zastosowaniem adnotacji w wątku jest sprawdzenie, czy metody lub klasy oznaczone adnotacjami @WorkerThread
są wywoływane tylko z odpowiedniego wątku w tle.
Adnotacje ograniczeń wartości
Aby sprawdzać wartości parametrów przekazywanych, użyj adnotacji @IntRange
, @FloatRange
i @Size
. Zarówno @IntRange
, jak i @FloatRange
są najbardziej przydatne w przypadku parametrów, w których przypadku użytkownicy mogą podać nieprawidłowy zakres.
Adnotacja @IntRange
sprawdza, czy wartość parametru typu integer lub long mieści się w określonym zakresie. W tym przykładzie parametr alpha
musi zawierać liczbę całkowitą od 0 do 255:
Kotlin
fun setAlpha(@IntRange(from = 0, to = 255) alpha: Int) { ... }
Java
public void setAlpha(@IntRange(from=0,to=255) int alpha) { ... }
Adnotacja @FloatRange
sprawdza, czy wartość parametru typu float lub double mieści się w określonym zakresie wartości zmiennoprzecinkowych. Ten przykład wskazuje, że parametr alpha
musi zawierać wartość zmiennoprzecinkową od 0,0 do 1,0:
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) {...}
Adnotacja @Size
sprawdza rozmiar kolekcji lub tablicy albo długość ciągu znaków. Adnotacji @Size
można używać do weryfikowania tych jakości:
- Minimalny rozmiar, np.
@Size(min=2)
- Maksymalny rozmiar, np.
@Size(max=2)
- Dokładny rozmiar, np.
@Size(2)
- Liczba, której wielokrotnością musi być rozmiar, np.
@Size(multiple=2)
Na przykład @Size(min=1)
sprawdza, czy kolekcja nie jest pusta, a @Size(3)
sprawdza, czy tablica zawiera dokładnie 3 wartości.
Z przykładu poniżej wynika, że tablica location
musi zawierać co najmniej 1 element:
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); }
adnotacje dotyczące uprawnień;
Użyj adnotacji @RequiresPermission
, aby zweryfikować uprawnienia wywołującego metodę. Aby sprawdzić, czy na liście prawidłowych uprawnień znajduje się określone uprawnienie, użyj atrybutu anyOf
. Aby sprawdzić zestaw uprawnień, użyj atrybutu allOf
. W tym przykładzie metoda setWallpaper()
jest opatrzona adnotacją, która wskazuje, że wywołujący tę metodę musi mieć uprawnienie permission.SET_WALLPAPERS
:
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;
Ten przykład wymaga, aby element wywołujący metodę copyImageFile()
miał dostęp zarówno do odczytu do pamięci zewnętrznej, jak i do odczytu metadanych lokalizacji w kopiowanym obrazie:
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) { //... }
W przypadku uprawnień do intencji umieść wymagane uprawnienia w polu ciągu, które określa nazwę działania intencji:
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";
W przypadku uprawnień dostawców treści, które wymagają oddzielnych uprawnień do odczytu i zapisu, owiń każde z nich w annotację @RequiresPermission.Read
lub @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");
Uprawnienia pośrednie
Jeśli uprawnienia zależą od konkretnej wartości podanej w parametrze metody, użyj @RequiresPermission
na samym parametrze, nie wymieniając konkretnych uprawnień.
Na przykład metoda startActivity(Intent)
korzysta z pośredniego uprawnienia do intencji przekazywanej do metody:
Kotlin
abstract fun startActivity(@RequiresPermission intent: Intent, bundle: Bundle?)
Java
public abstract void startActivity(@RequiresPermission Intent intent, @Nullable Bundle)
Gdy używasz uprawnień pośrednich, narzędzia do kompilacji przeprowadzają analizę przepływu danych, aby sprawdzić, czy argument przekazany do metody zawiera adnotacje @RequiresPermission
. Następnie wymusza wszelkie istniejące adnotacje z parametru w samej metodzie. W przykładzie startActivity(Intent)
adnotacje klasy Intent
powodują wyświetlenie ostrzeżeń o nieprawidłowym użyciu startActivity(Intent)
, gdy do metody zostanie przekazana intencja bez odpowiednich uprawnień, jak widać na rysunku 1.
Narzędzia do kompilacji generują ostrzeżenie w startActivity(Intent)
na podstawie adnotacji dotyczącej nazwy działania w intencji w klasie 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";
W razie potrzeby możesz zastąpić @RequiresPermission
wartością @RequiresPermission.Read
lub @RequiresPermission.Write
podczas dodawania adnotacji do parametru metody. Jednak w przypadku uprawnień pośrednich elementu @RequiresPermission
nie należy używać w połączeniu z adnotacjami uprawnień do odczytu ani zapisu.
Adnotacje wartości zwracanych
Użyj adnotacji @CheckResult
, aby sprawdzić, czy wynik metody lub zwracana wartość są rzeczywiście używane. Zamiast oznaczać @CheckResult
każdą metodę niepustą, dodaj adnotację, aby wyjaśnić wyniki potencjalnie mylących metod.
Na przykład nowi programiści Java często błędnie sądzą, że <String>.trim()
usuwa odstępy z oryginalnego ciągu. Adnotacje do metody z flagami @CheckResult
oznaczają użycie <String>.trim()
, gdy element wywołujący nie wykona żadnych działań związanych z zwracaną przez nią wartością.
Ten przykład opisuje metodę checkPermissions()
, która pozwala sprawdzić, czy zwracana jest wartość zwracana metody. Zawiera też nazwę metody enforcePermission()
, która zostanie zaproponowana deweloperowi jako zamiennik:
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);
Adnotacje CallSuper
Użyj adnotacji @CallSuper
, aby sprawdzić, czy metoda zastępowania wywołuje superimplementację.
W tym przykładzie metoda onCreate()
jest opatrzona adnotacjami, aby zapewnić, że wszystkie implementacje metody zastępczej wywołują metodę super.onCreate()
:
Kotlin
@CallSuper override fun onCreate(savedInstanceState: Bundle?) { }
Java
@CallSuper protected void onCreate(Bundle savedInstanceState) { }
Adnotacje typu
Adnotacje Typedef określają, czy określony parametr, zwracana wartość lub pole odwołuje się do konkretnego zestawu stałych. Umożliwiają też automatyczne uzupełnianie kodu, aby automatycznie oferować dozwolone stałe.
Użyj adnotacji @IntDef
i @StringDef
, aby utworzyć adnotacje z wyliczeniami zbiorów liczb całkowitych i ciągów znaków, które służą do sprawdzania innych typów odwołań do kodu.
Adnotacje typu „Typedef” używają instrukcji @interface
do deklarowania nowego typu adnotacji z wyliczeniem.
Adnotacje @IntDef
i @StringDef
wraz z adnotacją @Retention
adnotują nową adnotację i są niezbędne do zdefiniowania typu wyliczeniowego. Adnotacja @Retention(RetentionPolicy.SOURCE)
informuje kompilator, aby nie przechowywać danych adnotacji za pomocą enumeracji w pliku .class
.
W tym przykładzie pokazano, jak utworzyć adnotację, która sprawdza, czy wartość przekazana jako parametr metody odwołuje się do jednej z zdefiniowanych stałych:
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); }
Podczas kompilowania tego kodu generowane jest ostrzeżenie, jeśli parametr mode
nie odwołuje się do jednej z zdefiniowanych stałych (NAVIGATION_MODE_STANDARD
, NAVIGATION_MODE_LIST
lub NAVIGATION_MODE_TABS
).
Połącz @IntDef
i @IntRange
, aby wskazać, że liczba całkowita może być określonym zbiorem stałych lub wartością w zakresie.
Włącz łączenie stałych z flagami
Jeśli użytkownicy mogą łączyć dozwolone stałe z flagą (np. |
, &
, ^
itd.), możesz zdefiniować adnotację za pomocą atrybutu flag
, aby sprawdzić, czy parametr lub wartość zwracana odwołuje się do prawidłowego wzorca.
Ten przykład tworzy adnotację DisplayOptions
z listą prawidłowych stałych DISPLAY_
:
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 {} ...
Gdy kompilujesz kod z flagą adnotacji, generowane jest ostrzeżenie, jeśli ozdobiony parametr lub wartość zwracana nie odwołuje się do prawidłowego wzorca.
Zachowaj adnotację
Adnotacja @Keep
zapewnia, że adnotowana klasa lub metoda nie zostanie usunięta, gdy kod zostanie zminiaturyzowany w czasie kompilacji. Ta adnotacja jest zwykle dodawana do metod i klas, do których dostęp uzyskuje się za pomocą odbicia lustrzanego, aby zapobiec traktowaniu kodu przez kompilator jako nieużywanego.
Uwaga: klasy i metody, które dodajesz za pomocą adnotacji @Keep
, zawsze pojawiają się w pliku APK aplikacji, nawet jeśli nigdy nie odwołujesz się do tych klas i metod w jej logice.
Aby zmniejszyć rozmiar aplikacji, zastanów się, czy w aplikacji jest konieczne zachowanie każdej adnotacji @Keep
. Jeśli używasz odbicia lustrzanego, aby uzyskać dostęp do adnotowanej klasy lub metody, użyj w regułach ProGuard instrukcji warunkowej
-if
, określając klasę, która wykonuje wywołania odbicia lustrzanego.
Więcej informacji o minifikacji kodu i określaniu, którego kodu nie należy usuwać, znajdziesz w artykule Zmniejsz, zaciemnij i zoptymalizuj aplikację.
Adnotacje dotyczące widoczności kodu
Użyj poniższych adnotacji, aby wskazać widoczność określonych części kodu, takich jak metody, klasy, pola czy pakiety.
Udostępnianie kodu na potrzeby testowania
Adnotacja @VisibleForTesting
wskazuje, że adnotowana metoda jest bardziej widoczna niż zwykle, co ułatwia jej testowanie. Ta adnotacja ma opcjonalny argument otherwise
, który pozwala określić, jak widoczna miałaby być metoda, gdyby nie potrzeba wyświetlania jej na potrzeby testowania. Lint używa argumentu otherwise
, aby narzucić wymaganą widoczność.
W tym przykładzie wartość myMethod()
to zwykle private
, ale w przypadku testów jest to package-private
. Po oznaczeniu VisibleForTesting.PRIVATE
lint wyświetla komunikat, gdy ta metoda jest wywoływana spoza kontekstu, do którego zezwala dostęp private
, na przykład z innej jednostki kompilacji.
Kotlin
@VisibleForTesting(otherwise = VisibleForTesting.PRIVATE) fun myMethod() { ... }
Java
@VisibleForTesting(otherwise = VisibleForTesting.PRIVATE) void myMethod() { ... }
Możesz też podać @VisibleForTesting(otherwise = VisibleForTesting.NONE)
, aby wskazać, że metoda istnieje tylko do testowania. Ten formularz jest taki sam jak przy użyciu @RestrictTo(TESTS)
. Oba wykonują te same kontrole.
Ograniczanie interfejsu API
Adnotacja @RestrictTo
wskazuje, że dostęp do oznaczonego interfejsu API (pakietu, klasy lub metody) jest ograniczony w następujący sposób:
Podklasy
Aby ograniczyć dostęp do interfejsu API tylko do podklas, użyj formularza adnotacji @RestrictTo(RestrictTo.Scope.SUBCLASSES)
.
Dostęp do tego interfejsu API mają tylko klasy, które rozszerzają tę z adnotacjami. Modyfikator Java
protected
nie jest wystarczająco restrykcyjny, ponieważ zezwala na dostęp z niepowiązanych klas w tym samym pakiecie. Zdarzają się też sytuacje, w których chcesz zostawić metodę public
dla elastyczności w przyszłości, ponieważ nigdy nie można utworzyć metody protected
ani zastąpionej wcześniej public
, ale chcesz dać wskazówkę, że klasa jest przeznaczona do użycia w ramach klasy lub tylko do podklas.
Biblioteki
Użyj formularza adnotacji @RestrictTo(RestrictTo.Scope.LIBRARY_GROUP_PREFIX)
, aby ograniczyć dostęp przez interfejs API tylko do swoich bibliotek.
Dostęp do interfejsu API z adnotacjami ma tylko kod Twojej biblioteki. Dzięki temu możesz nie tylko porządkować kod w dowolnej hierarchii pakietu, ale też udostępniać go grupie powiązanych bibliotek. Ta opcja jest już dostępna w przypadku bibliotek Jetpacka, które zawierają dużo kodu implementacji, który nie jest przeznaczony do użytku zewnętrznego, ale musi być public
, aby udostępnić go w różnych uzupełniających bibliotekach Jetpacka.
Testowanie
Aby uniemożliwić innym programistom dostęp do interfejsów API do testowania, użyj formularza adnotacji @RestrictTo(RestrictTo.Scope.TESTS)
.
Do interfejsu API z adnotacjami dostęp ma tylko kod testowy. Zapobiega to używaniu przez innych programistów interfejsów API do celów programistycznych, które mają służyć tylko do testowania.