L'utilizzo di strumenti di ispezione del codice, come lint, può aiutarti a trovare
problemi e migliorare il codice, ma questi strumenti possono solo dedurre una parte delle informazioni. Gli ID delle risorse Android, ad esempio, utilizzano un int per identificare stringhe, elementi grafici, colori e altri tipi di risorse, quindi gli strumenti di ispezione non possono sapere quando hai specificato una risorsa stringa anziché una risorsa colore. In questa situazione, l'app potrebbe non essere visualizzata correttamente o non essere eseguita, anche se utilizzi l'ispezione del codice.
Le annotazioni ti consentono di fornire suggerimenti agli strumenti di ispezione del codice, come lint, per rilevare questi problemi di codice più sottili. Le annotazioni vengono aggiunte come tag di metadati che associ a variabili, parametri e valori restituiti per ispezionare i valori restituiti dei metodi, i parametri passati, le variabili locali e i campi. Se utilizzate con gli strumenti di ispezione del codice, le annotazioni possono aiutarti a rilevare problemi come le eccezioni di puntatore nullo e i conflitti di tipo di risorsa.
Android supporta una serie di annotazioni tramite la
libreria Jetpack Annotations.
Puoi accedere alla libreria tramite il pacchetto androidx.annotation.
Nota: se un modulo ha una dipendenza da un processore di annotazioni,
devi utilizzare la configurazione della dipendenza kapt o ksp per Kotlin
o la configurazione della dipendenza annotationProcessor per Java per aggiungere la
dipendenza.
Aggiungere annotazioni al progetto
Per attivare le annotazioni nel progetto, aggiungi la dipendenza androidx.annotation:annotation alla libreria o all'app. Le annotazioni che aggiungi vengono controllate quando esegui un'ispezione del codice o un'attività lint.
Aggiungere la dipendenza della libreria Jetpack Annotations
La libreria Jetpack Annotations è pubblicata nel
repository Maven di Google.
Per aggiungere la libreria Jetpack Annotations al progetto, includi la seguente
riga nel blocco dependencies del file build.gradle o
build.gradle.kts:
Kotlin
dependencies { implementation("androidx.annotation:annotation:1.10.0") }
Alla moda
dependencies { implementation 'androidx.annotation:annotation:1.10.0' }
Se utilizzi le annotazioni nel tuo modulo della libreria, queste vengono incluse come parte dell'artefatto dell'archivio Android (AAR) in formato XML nel file annotations.zip. L'aggiunta della dipendenza androidx.annotation non introduce una dipendenza per gli utenti downstream della tua libreria.
Nota: se utilizzi altre librerie Jetpack, potresti non dover aggiungere la dipendenza androidx.annotation. Poiché molte altre librerie Jetpack dipendono dalla libreria Annotations, potresti già avere accesso alle annotazioni.
Per un elenco completo delle annotazioni incluse nel repository Jetpack, consulta il
riferimento
della libreria Jetpack Annotations o utilizza la funzionalità di completamento automatico per visualizzare le opzioni disponibili per l'
import androidx.annotation. istruzione.
Eseguire ispezioni del codice
Per avviare un'ispezione del codice da Android Studio, che include la convalida delle annotazioni e il controllo lint automatico, seleziona Analizza > Ispeziona codice dal menu. Android Studio mostra messaggi di conflitto per segnalare potenziali problemi in cui il codice è in conflitto con le annotazioni e suggerisce possibili soluzioni.
Puoi anche applicare le annotazioni eseguendo l'attività running the
lint utilizzando la riga di comando. Sebbene questa operazione possa essere utile per segnalare problemi con un server di integrazione continua, l'attività lint non applica le annotazioni di nullità (descritte nella sezione seguente); solo Android Studio lo fa. Per ulteriori
informazioni sull'attivazione e l'esecuzione delle ispezioni lint, consulta Migliorare il codice con i controlli lint.
Sebbene i conflitti di annotazione generino avvisi, questi non impediscono la compilazione dell'app.
Annotazioni di nullità
Le annotazioni di nullità possono essere utili nel codice Java per applicare se i valori possono essere null. Sono meno utili nel codice Kotlin, poiché Kotlin ha regole di supporto di valori null integrate che vengono applicate in tempo di compilazione.Aggiungi le annotazioni @Nullable e @NonNull per controllare la nullità di una determinata variabile, un parametro o un valore restituito. L'annotazione @Nullable indica una variabile, un parametro o un valore restituito che può essere null.
@NonNull indica una variabile, un parametro o un valore restituito che non può essere null.
Ad esempio, se una variabile locale che contiene un valore null viene passata come parametro a un metodo con l'annotazione @NonNull collegata a quel parametro, la creazione del codice genera un avviso che indica un conflitto non null. Inoltre, se tenti di fare riferimento al risultato di un metodo contrassegnato da @Nullable senza prima verificare se il risultato è null, viene generato un avviso di nullità. Utilizza @Nullable sul valore restituito di un metodo solo se ogni utilizzo del metodo deve essere controllato esplicitamente per verificare la presenza di valori null.
L'esempio seguente mostra il supporto di valori null in azione. Il codice di esempio Kotlin non utilizza l'annotazione @NonNull perché viene aggiunta automaticamente al bytecode generato quando viene specificato un tipo non nullable. L'esempio Java utilizza l'annotazione @NonNull sui parametri context e attrs per verificare che i valori dei parametri passati non siano null. Verifica inoltre che il metodo onCreateView() stesso non restituisca 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) { ... } ...
Analisi di nullità
Android Studio supporta l'esecuzione di un'analisi del supporto di valori null per dedurre e inserire automaticamente le annotazioni nel codice. Un'analisi di nullità analizza i contratti nelle gerarchie dei metodi nel codice per rilevare:
- Metodi di chiamata che possono restituire null.
- Metodi che non devono restituire null.
- Variabili, come campi, variabili locali e parametri, che possono essere null.
- Variabili, come campi, variabili locali e parametri, che non possono contenere un valore null.
L'analisi inserisce automaticamente le annotazioni di null appropriate in nelle posizioni rilevate.
Per eseguire un'analisi di nullità in Android Studio, seleziona Analizza > Inferisci nullità. Android Studio inserisce le annotazioni Android @Nullable e @NonNull nelle posizioni rilevate nel codice. Dopo aver eseguito un'analisi di nullità, è consigliabile verificare le annotazioni inserite.
Nota: quando aggiungi annotazioni di nullità, il completamento automatico potrebbe
suggerire le annotazioni IntelliJ
@Nullable e
@NotNull anziché le annotazioni di nullità Android e potrebbe importare automaticamente la libreria corrispondente. Tuttavia, il controllo lint di Android Studio
cerca solo le annotazioni di nullità Android. Quando verifichi le
annotazioni, assicurati che il progetto utilizzi le annotazioni di nullità Android in modo che il
controllo lint possa notificarti correttamente durante l'ispezione del codice.
Annotazioni delle risorse
La convalida dei tipi di risorse può essere utile perché i riferimenti Android alle risorse, come le risorse drawable e string, vengono passati come numeri interi.
Il codice che prevede che un parametro faccia riferimento a un tipo specifico di risorsa, ad esempio una String,
può essere passato al tipo di riferimento previsto di int, ma in realtà fa riferimento a un tipo di risorsa diverso, ad esempio una risorsa R.string.
Ad esempio, aggiungi le @StringRes annotazioni per
verificare se un parametro di risorsa contiene un R.string riferimento, come mostrato di seguito:
Kotlin
abstract fun setTitle(@StringRes resId: Int)
Java
public abstract void setTitle(@StringRes int resId)
Durante l'ispezione del codice, l'annotazione genera un avviso se nel parametro non viene passato un riferimento R.string.
Le annotazioni per altri tipi di risorse, come @DrawableRes, @DimenRes, @ColorRes e @InterpolatorRes, possono essere
aggiunte utilizzando lo stesso formato di annotazione ed eseguite durante l'ispezione del codice.
Se il parametro supporta più tipi di risorse, puoi inserire più annotazioni di tipo di risorsa in un determinato parametro. Utilizza @AnyRes
per indicare che il parametro annotato può essere di qualsiasi tipo di risorsa R.
Sebbene tu possa utilizzare @ColorRes per specificare che un
parametro deve essere una risorsa colore, un numero intero di colore (nel formato RRGGBB o
AARRGGBB format) non viene riconosciuto come risorsa colore. Utilizza invece l'annotazione @ColorInt per
indicare che un parametro deve essere un numero intero di colore. Gli strumenti di build contrassegneranno il codice errato che passa un ID risorsa colore come android.R.color.black, anziché un numero intero di colore, ai metodi annotati.
Annotazioni dei thread
Le annotazioni dei thread verificano se un metodo viene chiamato da un tipo specifico di thread. Sono supportate le seguenti annotazioni dei thread:
Gli strumenti di build trattano le annotazioni @MainThread e @UiThread come intercambiabili, quindi puoi chiamare i metodi @UiThread dai metodi @MainThread e viceversa. Tuttavia, è possibile che un thread UI sia diverso dal thread principale, nel caso di app di sistema con più visualizzazioni su thread diversi. Pertanto, devi annotare i metodi associati alla gerarchia di oggetti View di un'app con @UiThread e annotare solo i metodi associati al ciclo di vita di un'app con @MainThread.
Se tutti i metodi di una classe condividono lo stesso requisito di threading, puoi aggiungere una singola annotazione di thread alla classe per verificare che tutti i metodi della classe vengano chiamati dallo stesso tipo di thread.
Un uso comune delle annotazioni dei thread è la convalida che i metodi o le classi annotati con
@WorkerThread vengano chiamati solo da un thread in background appropriato.
Annotazioni dei vincoli di valore
Utilizza le annotazioni @IntRange, @FloatRange e @Size per convalidare i valori dei parametri passati. Sia @IntRange sia @FloatRange sono più utili quando vengono applicate ai parametri in cui è probabile che gli utenti sbaglino l'intervallo.
L'annotazione @IntRange convalida che un valore di parametro intero o lungo rientri in un intervallo specificato. L'esempio seguente indica che il parametro alpha deve contenere un valore intero compreso tra 0 e 255:
Kotlin
fun setAlpha(@IntRange(from = 0, to = 255) alpha: Int) { ... }
Java
public void setAlpha(@IntRange(from=0,to=255) int alpha) { ... }
L'annotazione @FloatRange verifica se un valore di parametro float o double rientra in un intervallo specificato di valori a virgola mobile. L'esempio seguente indica che il parametro alpha deve contenere un valore float compreso tra 0.0 e 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) {...}
L'annotazione @Size controlla la dimensione di una raccolta o di un array o la lunghezza di una stringa. L'annotazione @Size può essere utilizzata per verificare
le seguenti qualità:
- Dimensione minima, ad esempio
@Size(min=2) - Dimensione massima, ad esempio
@Size(max=2) - Dimensione esatta, ad esempio
@Size(2) - Un numero di cui la dimensione deve essere un multiplo, ad esempio
@Size(multiple=2)
Ad esempio, @Size(min=1)
verifica se una raccolta non è vuota e @Size(3)
convalida che un array contenga esattamente tre valori.
L'esempio seguente indica che l'array location deve contenere almeno un elemento:
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); }
Annotazioni delle autorizzazioni
Utilizza l'@RequiresPermission
annotazione per convalidare le autorizzazioni del chiamante di un metodo. Per verificare una singola autorizzazione da un elenco di autorizzazioni valide, utilizza l'attributo anyOf. Per verificare un insieme di autorizzazioni, utilizza l'attributo allOf. L'esempio seguente annota il metodo setWallpaper() per indicare che il chiamante del metodo deve avere l'autorizzazione 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;
L'esempio seguente richiede che il chiamante del metodo copyImageFile() abbia sia l'accesso in lettura all'archivio esterno sia l'accesso in lettura ai metadati della posizione nell'immagine copiata:
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) { //... }
Per le autorizzazioni sugli intent, inserisci il requisito di autorizzazione nel campo stringa che definisce il nome dell'azione dell'intent:
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";
Per le autorizzazioni sui provider di contenuti che richiedono autorizzazioni separate per l'accesso in lettura e scrittura, racchiudi ogni requisito di autorizzazione in un'annotazione @RequiresPermission.Read
o @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");
Autorizzazioni indirette
Quando un'autorizzazione dipende dal valore specifico fornito al parametro di un metodo, utilizza @RequiresPermission sul parametro stesso senza elencare le autorizzazioni specifiche.
Ad esempio, il startActivity(Intent)
metodo utilizza un'autorizzazione indiretta sull'intent passato al metodo:
Kotlin
abstract fun startActivity(@RequiresPermission intent: Intent, bundle: Bundle?)
Java
public abstract void startActivity(@RequiresPermission Intent intent, @Nullable Bundle)
Quando utilizzi le autorizzazioni indirette, gli strumenti di build eseguono l'analisi del flusso di dati per verificare se l'argomento passato al metodo ha annotazioni @RequiresPermission. Quindi applicano le annotazioni esistenti dal parametro al metodo stesso. Nell'esempio
startActivity(Intent) le annotazioni nella classe Intent causano gli avvisi risultanti
sugli utilizzi non validi di startActivity(Intent) quando al metodo viene passato un intent senza le autorizzazioni
appropriate, come mostrato nella Figura 1.
Figura 1. L'avviso generato da un'annotazione di autorizzazioni indirette sul metodo startActivity(Intent).
Gli strumenti di build generano l'avviso su startActivity(Intent) dall'annotazione
sul nome dell'azione dell'intent corrispondente nella classe Intent class:
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";
Se necessario, puoi sostituire @RequiresPermission con
@RequiresPermission.Read o @RequiresPermission.Write quando annoti
il parametro di un metodo. Tuttavia, per le autorizzazioni indirette, @RequiresPermission non deve essere utilizzato insieme alle annotazioni delle autorizzazioni di lettura o scrittura.
Annotazioni dei valori restituiti
Utilizza l'annotazione @CheckResult per
convalidare che il risultato o il valore restituito di un metodo venga effettivamente utilizzato. Anziché annotare ogni metodo non void con @CheckResult, aggiungi l'annotazione per chiarire i risultati di metodi potenzialmente confusi.
Ad esempio, i nuovi sviluppatori Java spesso pensano erroneamente che
<String>.trim() rimuova gli spazi vuoti dalla stringa originale. L'annotazione
del metodo con @CheckResult contrassegna gli utilizzi di <String>.trim()
in cui il chiamante non esegue alcuna operazione con il valore restituito del metodo.
L'esempio seguente annota il checkPermissions()
metodo per verificare se viene fatto riferimento al valore restituito del metodo. Inoltre, denomina il enforcePermission()
metodo come metodo da suggerire allo sviluppatore come sostituzione:
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);
Annotazioni CallSuper
Utilizza l'annotazione @CallSuper per
convalidare che un metodo di override chiami l'implementazione super del metodo.
L'esempio seguente
annota il metodo onCreate() per garantire che tutte le implementazioni dei metodi di override
chiamino super.onCreate():
Kotlin
@CallSuper override fun onCreate(savedInstanceState: Bundle?) { }
Java
@CallSuper protected void onCreate(Bundle savedInstanceState) { }
Annotazioni Typedef
Le annotazioni Typedef verificano se un determinato parametro, valore restituito, o campo fa riferimento a un insieme specifico di costanti. Consentono inoltre al completamento del codice di offrire automaticamente le costanti consentite.
Utilizza le annotazioni @IntDef e @StringDef per creare annotazioni enumerate di insiemi di numeri interi e stringhe per convalidare altri tipi di riferimenti al codice.
Le annotazioni Typedef utilizzano @interface per dichiarare il nuovo tipo di annotazione enumerata.
Le annotazioni @IntDef e @StringDef, insieme a @Retention, annotano la nuova annotazione e sono necessarie per definire il tipo enumerato. L'annotazione @Retention(RetentionPolicy.SOURCE) indica al compilatore di non memorizzare i dati delle annotazioni enumerate nel file .class.
L'esempio seguente mostra i passaggi per creare un'annotazione che verifica se un valore passato come parametro di un metodo fa riferimento a una delle costanti definite:
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); }
Quando crei questo codice, viene generato un avviso se il parametro mode non fa riferimento a una delle costanti definite (NAVIGATION_MODE_STANDARD,
NAVIGATION_MODE_LIST, o NAVIGATION_MODE_TABS).
Combina @IntDef e @IntRange per indicare che un numero intero può essere un determinato insieme di costanti o un valore all'interno di un intervallo.
Attivare la combinazione di costanti con i flag
Se gli utenti possono combinare le costanti consentite con un flag (ad esempio |, &, ^ e così via), puoi definire un'annotazione con un attributo flag per verificare se un parametro o un valore restituito fa riferimento a un pattern valido.
L'esempio seguente crea l'annotazione DisplayOptions con un elenco di costanti DISPLAY_ valide:
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 {} ...
Quando crei codice con un flag di annotazione, viene generato un avviso se il parametro o il valore restituito decorato non fa riferimento a un pattern valido.
Annotazione Keep
L'annotazione @Keep garantisce che una classe o un metodo annotato non venga rimosso quando il codice viene minimizzato in fase di compilazione. Questa annotazione viene in genere aggiunta a metodi e classi a cui si accede tramite reflection per impedire al compilatore di trattare il codice come inutilizzato.
Attenzione: le classi e i metodi annotati
con @Keep vengono sempre visualizzati nell'APK dell'app, anche se non fai mai
riferimento a queste classi e metodi nella logica dell'app.
Per mantenere le dimensioni dell'app ridotte, valuta se è necessario conservare
ogni @Keep annotazione nell'app. Se utilizzi la reflection per
accedere a una classe o a un metodo annotato, utilizza una
-if condizione nelle regole ProGuard, specificando la classe
che effettua le chiamate di reflection.
Per ulteriori informazioni su come minimizzare il codice e specificare il codice da non rimuovere, consulta Ridurre, offuscare e ottimizzare l'app.
Annotazioni della visibilità del codice
Utilizza le seguenti annotazioni per indicare la visibilità di porzioni specifiche di codice, come metodi, classi, campi o pacchetti.
Rendere il codice visibile per i test
L'annotazione @VisibleForTesting indica che un metodo annotato è più visibile del necessario per rendere il metodo testabile. Questa annotazione ha un argomento otherwise facoltativo che ti consente di designare la visibilità del metodo se non fosse necessario renderlo visibile per i test. Lint utilizza l'argomento otherwise per applicare la visibilità prevista.
Nell'esempio seguente, myMethod() è normalmente private, ma è
package-private per i test. Con la VisibleForTesting.PRIVATE
designazione, lint visualizza un messaggio se questo metodo viene chiamato dall'esterno del
contesto consentito dall'accesso private, ad esempio da un'unità di compilazione diversa.
Kotlin
@VisibleForTesting(otherwise = VisibleForTesting.PRIVATE) fun myMethod() { ... }
Java
@VisibleForTesting(otherwise = VisibleForTesting.PRIVATE) void myMethod() { ... }
Puoi anche specificare @VisibleForTesting(otherwise = VisibleForTesting.NONE)
per indicare che un metodo esiste solo per i test. Questo modulo è uguale all'utilizzo di
@RestrictTo(TESTS). Entrambi eseguono lo stesso controllo lint.
Limitare un'API
L'annotazione @RestrictTo
indica che l'accesso all'API annotata (pacchetto, classe o metodo) è limitato,
come segue:
Sottoclassi
Utilizza il modulo di annotazione @RestrictTo(RestrictTo.Scope.SUBCLASSES) per limitare
l'accesso all'API solo alle sottoclassi.
Solo le classi che estendono la classe annotata possono accedere a questa API. Il modificatore
protected di Java non è sufficientemente restrittivo, perché consente l'accesso
da classi non correlate all'interno dello stesso pacchetto. Inoltre, in alcuni casi potresti voler lasciare un
metodo public per una maggiore flessibilità futura, perché non puoi mai rendere public un metodo
protected e di override precedente, ma vuoi fornire un
suggerimento che la classe è destinata all'utilizzo all'interno della classe o solo dalle sottoclassi.
Librerie
Utilizza il modulo di annotazione @RestrictTo(RestrictTo.Scope.LIBRARY_GROUP_PREFIX) per
limitare l'accesso all'API solo alle tue librerie.
Solo il codice della libreria può accedere all'API annotata. In questo modo, non solo puoi organizzare il codice
nella gerarchia dei pacchetti che preferisci, ma anche condividere
il codice tra un gruppo di librerie correlate. Questa opzione è già disponibile per le librerie Jetpack
che hanno una grande quantità di codice di implementazione non destinato all'uso esterno, ma che
deve essere public per condividerlo tra le varie librerie Jetpack complementari.
Test
Utilizza il modulo di annotazione @RestrictTo(RestrictTo.Scope.TESTS) per impedire ad altri sviluppatori di accedere alle tue API di test.
Solo il codice di test può accedere all'API annotata. In questo modo, altri sviluppatori non possono utilizzare le API per lo sviluppo che intendi utilizzare solo per i test.