Memperbaiki pemeriksaan kode dengan anotasi

Penggunaan alat pemeriksaan kode seperti lint dapat membantu Anda menemukan masalah dan meningkatkan kualitas kode, tetapi kemampuan alat pemeriksaan hanya sebatas itu. ID resource Android, misalnya, menggunakan int untuk mengidentifikasi string, grafis, warna, dan jenis resource lainnya, sehingga alat pemeriksaan tidak dapat membedakan ketika Anda menetapkan resource string saat Anda semestinya menetapkan resource warna. Situasi ini dapat mengakibatkan aplikasi Anda salah dirender atau gagal dijalankan sama sekali, sekalipun Anda menggunakan pemeriksaan kode.

Dengan anotasi, Anda dapat menyediakan petunjuk untuk alat pemeriksaan kode, seperti lint, untuk membantu mendeteksi masalah kode yang sulit dideteksi ini. Anotasi ditambahkan sebagai tag metadata yang dilampirkan ke variabel, parameter, dan nilai yang ditampilkan untuk memeriksa nilai yang ditampilkan metode, parameter yang diteruskan, variabel lokal, dan kolom. Saat digunakan dengan alat pemeriksaan kode, anotasi dapat membantu Anda mendeteksi masalah, seperti pengecualian pointer null dan konflik jenis resource.

Android mendukung berbagai anotasi melalui Library Jetpack Annotations. Anda dapat mengakses library ini melalui paket androidx.annotation.

Catatan: Jika ada modul yang memiliki dependensi pada pemroses anotasi, Anda harus menggunakan konfigurasi dependensi kapt atau ksp untuk Kotlin atau konfigurasi dependensi annotationProcessor untuk Java guna menambahkan dependensi tersebut.

Menambahkan anotasi ke project

Untuk mengaktifkan anotasi dalam project Anda, tambahkan dependensi androidx.annotation:annotation ke library atau aplikasi Anda. Setiap anotasi yang ditambahkan akan diperiksa saat Anda menjalankan pemeriksaan kode atau tugas lint.

Menambahkan dependensi library Jetpack Annotations

Library Jetpack Annotations dipublikasikan di Repositori Maven Google. Untuk menambahkan library Jetpack Annotations ke project Anda, sertakan baris berikut dalam blok dependencies file build.gradle atau build.gradle.kts:

Kotlin

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

Groovy

dependencies {
    implementation 'androidx.annotation:annotation:1.8.2'
}
Selanjutnya, di toolbar atau notifikasi sinkronisasi yang muncul, klik Sync Now.

Jika Anda menggunakan anotasi dalam modul library Anda sendiri, anotasi tersebut akan disertakan sebagai bagian dari artefak Android Archive (AAR) dalam format XML di file annotations.zip. Menambahkan dependensi androidx.annotation tidak akan memperkenalkan dependensi untuk pengguna downstream library Anda.

Catatan: Jika menggunakan library Jetpack lainnya, Anda mungkin tidak perlu menambahkan dependensi androidx.annotation. Karena banyak library Jetpack lain bergantung pada Library Annotations, Anda mungkin sudah memiliki akses ke anotasi tersebut.

Untuk daftar lengkap anotasi yang disertakan dalam repositori Jetpack, lihat referensi library Jetpack Annotations atau gunakan fitur pelengkapan otomatis guna menampilkan opsi yang tersedia untuk pernyataan import androidx.annotation..

Menjalankan pemeriksaan kode

Untuk memulai pemeriksaan kode dari Android Studio yang menyertakan validasi anotasi dan pemeriksaan lint otomatis, pilih Analyze > Inspect Code dari menu. Android Studio menampilkan pesan konflik untuk menandai potensi masalah apabila kode Anda bertentangan dengan anotasi dan menyarankan kemungkinan resolusi.

Anda juga dapat menerapkan anotasi dengan menjalankan tugas lint menggunakan command line. Meskipun cara ini mungkin berguna untuk menandai masalah server continuous integration, tugas lint tidak menerapkan anotasi nullness (dijelaskan di bagian berikut); hanya Android Studio yang melakukan penerapan ini. Untuk mengetahui informasi selengkapnya tentang cara mengaktifkan dan menjalankan pemeriksaan lint, lihat Meningkatkan kualitas kode dengan lint.

Meskipun konflik anotasi menghasilkan peringatan, peringatan ini tidak mencegah aplikasi Anda melakukan kompilasi.

Anotasi nullness

Anotasi nullness dapat berguna dalam kode Java untuk menerapkan kemungkinan nilai menjadi null. Fungsi ini kurang berguna dalam kode Kotlin karena Kotlin telah membuat aturan nullability yang diterapkan pada waktu kompilasi.

Tambahkan anotasi @Nullable dan @NonNull untuk memeriksa nullness variabel, parameter, atau nilai yang ditampilkan tertentu. Anotasi @Nullable menunjukkan variabel, parameter, atau nilai yang ditampilkan tertentu yang boleh bernilai null. @NonNull menunjukkan variabel, parameter, atau nilai yang ditampilkan yang tidak boleh bernilai null.

Misalnya, jika sebuah variabel lokal yang berisi nilai null diteruskan sebagai parameter ke metode dengan anotasi @NonNull yang dilampirkan ke parameter tersebut, pembuatan kode akan menghasilkan peringatan yang menunjukkan konflik non-null. Selain itu, mencoba merujuk hasil metode yang ditandai dengan @Nullable tanpa terlebih dahulu memeriksa apakah hasilnya bernilai null akan menghasilkan peringatan nullness. Hanya gunakan @Nullable pada nilai yang ditampilkan metode jika setiap penggunaan metode ini harus diperiksa secara eksplisit nilai null-nya.

Contoh berikut menunjukkan cara kerja nullability. Kode contoh Kotlin tidak memanfaatkan anotasi @NonNull karena akan otomatis ditambahkan ke bytecode yang dihasilkan saat jenis non-nullable ditentukan. Contoh Java memanfaatkan anotasi @NonNull pada parameter context dan attrs untuk memeriksa bahwa nilai parameter yang diteruskan bukan null. Contoh ini juga memeriksa bahwa metode onCreateView() tersebut tidak menghasilkan 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) {
      ...
      }
...

Analisis nullability

Android Studio mendukung operasi analisis nullability untuk otomatis menyimpulkan dan memasukkan anotasi nullness di kode Anda. Analisis nullability akan memindai kontrak di seluruh hierarki metode dalam kode Anda untuk mendeteksi:

  • Metode panggilan yang dapat menghasilkan null.
  • Metode yang tidak boleh menghasilkan null.
  • Variabel, seperti kolom, variabel lokal, dan parameter, yang boleh bernilai null.
  • Variabel, seperti kolom, variabel lokal, dan parameter, yang tidak boleh bernilai null.

Selanjutnya, analisis akan otomatis menyisipkan anotasi null yang sesuai di lokasi yang dideteksi.

Untuk menjalankan analisis nullability di Android Studio, pilih Analyze > Infer Nullity. Android Studio akan menyisipkan anotasi @Nullable dan @NonNull Android di lokasi yang terdeteksi dalam kode Anda. Setelah menjalankan analisis null, sebaiknya Anda memverifikasi anotasi yang dimasukkan tersebut.

Catatan: Saat menambahkan anotasi nullness, alat pelengkapan otomatis mungkin menyarankan anotasi @Nullable dan @NotNull IntelliJ, bukan anotasi null Android, dan dapat otomatis mengimpor library yang terkait. Namun, pemeriksa lint Android Studio hanya mencari anotasi null Android. Saat memverifikasi anotasi, pastikan bahwa project Anda menggunakan anotasi null Android agar pemeriksa lint dapat memberi tahu Anda dengan tepat selama pemeriksaan kode.

Anotasi resource

Memvalidasi jenis resource dapat berguna karena referensi Android ke berbagai resource, misalnya resource drawable dan string, diteruskan sebagai integer.

Kode yang mengharapkan parameter untuk merujuk ke jenis resource tertentu, seperti String, dapat diteruskan ke jenis referensi int yang diharapkan, tetapi sebenarnya merujuk ke jenis resource berbeda, seperti resource R.string.

Sebagai contoh, tambahkan anotasi @StringRes untuk memastikan parameter resource berisi referensi R.string, seperti yang ditampilkan di sini:

Kotlin

abstract fun setTitle(@StringRes resId: Int)

Java

public abstract void setTitle(@StringRes int resId)

Selama pemeriksaan kode, anotasi akan menghasilkan peringatan jika referensi R.string tidak diteruskan dalam parameter.

Anotasi untuk jenis resource lainnya, seperti @DrawableRes, @DimenRes, @ColorRes, dan @InterpolatorRes dapat ditambahkan menggunakan format anotasi yang sama dan dijalankan selama pemeriksaan kode.

Jika parameter mendukung beberapa jenis resource, Anda dapat menempatkan lebih dari satu anotasi jenis resource pada parameter tertentu. Gunakan @AnyRes untuk menunjukkan bahwa parameter yang dianotasi dapat berupa resource R jenis apa pun.

Meskipun Anda dapat menggunakan @ColorRes untuk menentukan bahwa parameter harus berupa resource warna, integer warna (dalam format RRGGBB atau AARRGGBB) tidak akan dikenali sebagai resource warna. Sebagai gantinya, gunakan anotasi @ColorInt untuk menunjukkan bahwa suatu parameter harus berupa integer warna. Alat build akan menandai kode salah yang meneruskan ID resource warna seperti android.R.color.black, bukannya integer warna, ke metode yang dianotasi.

Anotasi thread

Anotasi thread memeriksa apakah sebuah metode dipanggil dari thread jenis tertentu. Berikut adalah anotasi thread yang didukung:

Alat build memperlakukan anotasi @MainThread dan @UiThread sebagai dapat dipertukarkan sehingga Anda dapat memanggil metode @UiThread dari metode @MainThread, dan sebaliknya. Namun, ada kemungkinan UI thread berbeda dengan thread utama pada aplikasi sistem yang memiliki beberapa tampilan dalam thread yang berbeda. Oleh karena itu, sebaiknya Anda menganotasi metode yang terkait dengan hierarki tampilan aplikasi dengan @UiThread, dan hanya menganotasi metode yang terkait dengan siklus proses aplikasi dengan @MainThread.

Jika semua metode di sebuah class memiliki persyaratan threading yang sama, Anda dapat menambahkan anotasi thread tunggal ke class tersebut guna memverifikasi bahwa semua metode dalam class ini dipanggil dari jenis thread yang sama.

Penggunaan anotasi thread yang umum adalah untuk memvalidasi bahwa metode atau class yang dianotasikan dengan @WorkerThread hanya dipanggil dari thread latar belakang yang sesuai.

Anotasi batasan nilai

Gunakan anotasi @IntRange, @FloatRange, dan @Size untuk memvalidasi nilai parameter yang diteruskan. @IntRange dan @FloatRange akan sangat berguna jika diterapkan pada parameter dengan rentang yang cenderung sering salah ditetapkan oleh pengguna.

Anotasi @IntRange memvalidasi bahwa nilai parameter integer atau long berada dalam rentang yang ditetapkan. Contoh berikut menunjukkan bahwa parameter alpha harus berisi nilai bilangan bulat antara 0 sampai 255:

Kotlin

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

Java

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

Anotasi @FloatRange memastikan bahwa nilai parameter float atau double berada dalam rentang nilai floating point yang ditetapkan. Contoh berikut menunjukkan bahwa parameter alpha harus berisi nilai float antara 0,0 sampai 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) {...}

Anotasi @Size memeriksa ukuran kumpulan, array, atau panjang string. Anotasi @Size dapat digunakan untuk memverifikasi kualitas berikut:

  • Ukuran minimum, misalnya @Size(min=2)
  • Ukuran maksimum, misalnya @Size(max=2)
  • Ukuran persis, misalnya @Size(2)
  • Angka dengan ukuran yang harus dalam kelipatan, seperti @Size(multiple=2)

Misalnya, @Size(min=1) memastikan kumpulan tidak kosong, dan @Size(3) memvalidasi bahwa array berisi persis tiga nilai.

Contoh berikut menunjukkan bahwa array location harus berisi setidaknya satu elemen:

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);
}

Anotasi izin

Gunakan anotasi @RequiresPermission untuk memvalidasi izin pemanggil metode. Untuk memeriksa keberadaan izin tunggal dari daftar izin yang valid, gunakan atribut anyOf. Untuk memeriksa keberadaan sekumpulan izin, gunakan atribut allOf. Contoh berikut menganotasi metode setWallpaper() untuk menunjukkan bahwa pemanggil metode harus memiliki izin 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;

Contoh berikut mengharuskan pemanggil metode copyImageFile() memiliki akses baca ke penyimpanan eksternal dan akses baca ke metadata lokasi pada gambar yang disalin:

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) {
    //...
}

Untuk izin terkait intent, tempatkan persyaratan izin pada kolom string yang menentukan nama tindakan 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";

Untuk izin terkait penyedia konten yang memerlukan izin terpisah untuk akses baca dan tulis, gabungkan setiap persyaratan izin dalam anotasi @RequiresPermission.Read atau @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");

Izin tidak langsung

Jika izin bergantung pada nilai spesifik yang dimasukkan ke parameter metode, gunakan @RequiresPermission pada parameter itu sendiri tanpa mencantumkan izin spesifiknya. Misalnya, metode startActivity(Intent) menggunakan izin tidak langsung pada intent yang diteruskan ke metode:

Kotlin

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

Java

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

Saat Anda menggunakan izin tidak langsung, alat build akan menjalankan analisis alur data untuk memeriksa apakah argumen yang diteruskan ke dalam metode memiliki anotasi @RequiresPermission. Selanjutnya, alat build akan memberlakukan semua anotasi yang ada dari parameter pada metode itu sendiri. Dalam contoh startActivity(Intent), anotasi di class Intent menyebabkan munculnya peringatan tentang penggunaan startActivity(Intent) yang tidak valid saat intent tanpa izin yang sesuai diteruskan ke metode, seperti ditunjukkan pada gambar 1.

Gambar 1. Peringatan yang dihasilkan dari anotasi izin tidak langsung pada metode startActivity(Intent).

Alat build mengeluarkan peringatan tentang startActivity(Intent) dari anotasi pada nama tindakan intent yang terkait dalam class 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";

Jika perlu, Anda dapat mengganti @RequiresPermission dengan @RequiresPermission.Read atau @RequiresPermission.Write saat menganotasikan parameter metode. Namun, untuk izin tidak langsung, @RequiresPermission tidak boleh digunakan bersama anotasi izin baca atau tulis.

Anotasi nilai kembalian

Gunakan anotasi @CheckResult untuk memvalidasi bahwa hasil atau nilai kembalian dari sebuah metode benar-benar digunakan. Daripada menganotasi setiap metode non-void dengan @CheckResult, tambahkan anotasi ini untuk memperjelas hasil metode yang berpotensi membingungkan.

Misalnya, developer Java baru sering keliru menganggap bahwa <String>.trim() menghapus spasi kosong dari string asli. Menganotasi metode dengan @CheckResult akan menandai penggunaan <String>.trim() saat pemanggil tidak melakukan apa pun terhadap nilai yang ditampilkan metode.

Contoh berikut menganotasi metode checkPermissions() untuk memeriksa apakah nilai yang ditampilkan metode benar-benar direferensikan. Contoh ini juga menyebutkan enforcePermission() sebagai metode yang akan disarankan ke developer sebagai pengganti:

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);

Anotasi CallSuper

Gunakan anotasi @CallSuper untuk memvalidasi bahwa metode pengganti memanggil implementasi super untuk metode tersebut.

Contoh berikut menganotasi metode onCreate() untuk memastikan bahwa implementasi metode pengganti memanggil super.onCreate():

Kotlin

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

Java

@CallSuper
protected void onCreate(Bundle savedInstanceState) {
}

Anotasi Typedef

Anotasi Typedef memeriksa apakah parameter, nilai kembali, atau kolom tertentu merujuk ke kumpulan konstanta tertentu. Anotasi ini juga memungkinkan pelengkapan kode untuk otomatis menawarkan konstanta yang diizinkan.

Gunakan anotasi @IntDef dan @StringDef untuk membuat anotasi terenumerasi kumpulan integer dan string untuk memvalidasi jenis referensi kode lainnya.

Anotasi Typedef menggunakan @interface untuk mendeklarasikan jenis anotasi terenumerasi yang baru. Anotasi @IntDef dan @StringDef, beserta @Retention, menganotasi anotasi baru ini dan diperlukan untuk menentukan jenis terenumerasi. Anotasi @Retention(RetentionPolicy.SOURCE) memberi tahu compiler untuk tidak menyimpan data anotasi terenumerasi dalam file .class.

Contoh berikut menunjukkan langkah-langkah pembuatan anotasi yang memeriksa apakah suatu nilai diteruskan sebagai parameter metode yang mereferensikan salah satu konstanta yang ditentukan:

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);
}

Saat Anda membuat kode ini, peringatan akan dikeluarkan jika parameter mode tidak mereferensikan salah satu konstanta yang ditentukan (NAVIGATION_MODE_STANDARD, NAVIGATION_MODE_LIST, atau NAVIGATION_MODE_TABS).

Kombinasikan @IntDef dan @IntRange untuk menunjukkan bahwa integer dapat berupa sekumpulan konstanta tertentu atau nilai dalam suatu rentang.

Mengaktifkan penggabungan konstanta dengan tanda

Jika pengguna dapat menggabungkan konstanta yang diizinkan dengan sebuah tanda (misalnya |, &, ^, dan seterusnya), Anda dapat menetapkan anotasi dengan atribut flag untuk memeriksa apakah parameter atau nilai yang ditampilkan merujuk pola yang valid.

Contoh berikut akan membuat anotasi DisplayOptions dengan daftar konstanta DISPLAY_ yang valid:

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 {}

...

Saat Anda membuat kode dengan tanda anotasi, peringatan akan dikeluarkan jika parameter yang didekorasi atau nilai yang ditampilkan tidak merujuk pola yang valid.

Anotasi Keep

Anotasi @Keep memastikan bahwa class atau metode yang dianotasi tidak dihapus saat kode diminifikasi selama proses build. Anotasi ini biasanya ditambahkan ke metode dan class yang diakses melalui refleksi untuk mencegah compiler menganggap bahwa kode tidak digunakan.

Perhatian: Class dan metode yang dianotasi menggunakan @Keep akan selalu muncul di APK aplikasi, sekalipun Anda tidak pernah mereferensikan class dan metode tersebut dalam logika aplikasi.

Agar ukuran aplikasi tetap kecil, pertimbangkan perlu tidaknya mempertahankan setiap anotasi @Keep dalam aplikasi Anda. Jika Anda menggunakan refleksi untuk mengakses class atau metode yang dianotasi, gunakan kondisional -if dalam aturan ProGuard, dengan menentukan class yang membuat panggilan refleksi tersebut.

Untuk mengetahui informasi selengkapnya tentang cara meminifikasi kode dan menentukan kode yang tidak boleh dihapus, lihat Menyingkat, meng-obfuscate, dan mengoptimalkan aplikasi.

Anotasi visibilitas kode

Gunakan anotasi berikut untuk menunjukkan visibilitas bagian kode tertentu, seperti metode, class, kolom, atau paket.

Membuat kode terlihat untuk pengujian

Anotasi @VisibleForTesting menunjukkan bahwa metode yang dianotasi terlihat lebih mencolok daripada biasanya agar metode tersebut lebih mudah diuji. Anotasi ini memiliki argumen otherwise opsional yang memungkinkan Anda menentukan visibilitas metode jika tidak dimaksudkan untuk membuatnya terlihat selama pengujian. Lint menggunakan argumen otherwise untuk memberlakukan visibilitas yang diinginkan.

Dalam contoh berikut, myMethod() biasanya adalah private, tetapi anotasi untuk pengujian adalah package-private. Dengan penetapan VisibleForTesting.PRIVATE, lint akan menampilkan pesan jika metode ini dipanggil dari luar konteks yang diizinkan oleh akses private, misalnya dari unit kompilasi yang berbeda.

Kotlin

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

Java

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

Anda juga dapat menentukan @VisibleForTesting(otherwise = VisibleForTesting.NONE) untuk menunjukkan bahwa sebuah metode hanya ada untuk pengujian. Formatnya sama dengan penggunaan @RestrictTo(TESTS). Keduanya menjalankan pemeriksaan lint yang sama.

Membatasi API

Anotasi @RestrictTo menunjukkan bahwa akses ke API teranotasi (paket, class, atau metode) dibatasi sebagai berikut:

Subclass

Gunakan format anotasi @RestrictTo(RestrictTo.Scope.SUBCLASSES) untuk membatasi akses API ke subclass saja.

Hanya class yang memperluas class teranotasi yang dapat mengakses API ini. Modifier protected Java tidak cukup ketat karena masih memungkinkan akses dari class yang tidak terkait dalam paket yang sama. Selain itu, ada kemungkinan Anda ingin membiarkan metode public demi fleksibilitas di masa mendatang karena Anda tidak akan pernah dapat membuat protected sebelumnya dan public metode yang diganti, tetapi Anda ingin memberikan petunjuk bahwa class tersebut dimaksudkan untuk penggunaan dalam class itu atau dari subclass tertentu saja.

Library

Gunakan format anotasi @RestrictTo(RestrictTo.Scope.LIBRARY_GROUP_PREFIX) untuk membatasi akses API hanya ke library Anda.

Hanya kode library Anda yang dapat mengakses API teranotasi. Dengan begitu, Anda tidak hanya dapat mengatur kode dalam hierarki paket apa pun yang diinginkan, tetapi juga membagikan kode di antara sekumpulan library yang terkait. Opsi ini sudah tersedia untuk library Jetpack yang memiliki banyak kode implementasi yang tidak dimaksudkan untuk penggunaan eksternal, tetapi library tersebut harus berupa public agar dapat dibagikan ke berbagai library Jetpack pelengkap.

Pengujian

Gunakan format anotasi @RestrictTo(RestrictTo.Scope.TESTS) untuk mencegah developer lain mengakses API pengujian Anda.

Hanya kode pengujian yang dapat mengakses API teranotasi. Anotasi ini mencegah developer lain menggunakan API Anda untuk keperluan pengembangan, sementara Anda menyediakannya untuk keperluan pengujian saja.