Cải thiện việc kiểm tra mã bằng chú thích

Sử dụng bộ sưu tập để sắp xếp ngăn nắp các trang Lưu và phân loại nội dung dựa trên lựa chọn ưu tiên của bạn.

Việc sử dụng các công cụ kiểm tra mã như Lint có thể giúp bạn tìm ra vấn đề và cải thiện mã, nhưng đa phần thì các công cụ kiểm tra chỉ có thể suy luận và dự đoán. Chẳng hạn, các giá trị nhận dạng tài nguyên Android sử dụng int để xác định chuỗi, đồ hoạ, màu sắc và các kiểu tài nguyên khác, do đó, các công cụ kiểm tra không thể biết nên chỉ định tài nguyên chuỗi lúc nào hoặc nên chỉ định một màu nào đó ở đâu. Trong trường hợp này, ứng dụng có thể hiển thị không chính xác hoặc không chạy được, ngay cả khi đã sử dụng công cụ kiểm tra mã.

Các chú thích cho phép bạn cung cấp gợi ý cho các công cụ kiểm tra mã như Lint giúp phát hiện các vấn đề tinh vi hơn về mã. Các chú thích này được thêm dưới dạng thẻ siêu dữ liệu đính kèm vào các biến, tham số và giá trị trả về để kiểm tra các giá trị trả về của phương thức, các tham số đã chuyển, các biến cục bộ, và các trường. Khi được sử dụng cùng với các công cụ kiểm tra mã, các chú thích có thể giúp bạn phát hiện các vấn đề, chẳng hạn như các ngoại lệ con trỏ rỗng và các xung đột kiểu tài nguyên.

Android hỗ trợ nhiều chú thích thông qua Thư viện hỗ trợ chú thích. Bạn có thể truy cập vào thư viện thông qua gói android.support.annotation.

Lưu ý: Nếu một mô-đun có một phần phụ thuộc trên trình xử lý chú thích, thì bạn phải sử dụng cấu hình phần phụ thuộc "annotationProcessor" để thêm phần phụ thuộc đó. Để tìm hiểu thêm, hãy đọc bài viết Sử dụng cấu hình phần phụ thuộc trình xử lý chú thích.

Thêm chú giải vào dự án

Để bật các chú thích trong dự án, hãy thêm phần phụ thuộc support-annotations vào thư viện hoặc ứng dụng. Bất kỳ chú thích nào được thêm vào đều được kiểm tra khi chạy công cụ kiểm tra mã hoặc tác vụ lint.

Thêm phần phụ thuộc của thư viện chú giải hỗ trợ

Thư viện Chú thích hỗ trợ (Support Annotations library) được xuất bản trên Kho lưu trữ Maven của Google. Để thêm thư viện Chú thích hỗ trợ vào dự án, hãy thêm dòng sau trong khối dependencies của tệp build.gradle:

Groovy

dependencies {
    implementation 'com.android.support:support-annotations:28.0.0'
}

Kotlin

dependencies {
    implementation("com.android.support:support-annotations:28.0.0")
}
Sau đó, trong thanh công cụ hoặc thông báo đồng bộ hoá sẽ xuất hiện, hãy nhấp vào Đồng bộ hoá ngay (Sync Now).

Nếu bạn sử dụng các chú thích trong mô-đun thư viện của riêng mình, thì các chú thích đó sẽ được đính kèm như một phần của Cấu phần phần mềm Lưu trữ Android (AAR) ở định dạng XML trong tệp annotations.zip. Việc thêm phần phụ thuộc support-annotations sẽ không giới thiệu một phần phụ thuộc đến bất kỳ người dùng hạ nguồn (downstream user) nào sử dụng thư viện của bạn.

Lưu ý: Nếu đang sử dụng thư viện appcompat, bạn không cần thêm phần phụ thuộc support-annotations. Vì thư viện appcompat đã phụ thuộc vào thư viện Chú thích, nên bạn có quyền truy cập vào các chú thích đó.

Để xem danh sách đầy đủ các chú thích có trong kho lưu trữ hỗ trợ, hãy kiểm tra Tài liệu tham khảo về thư viện Chú thích hỗ trợ hoặc sử dụng tính năng tự động hoàn thành (auto-complete) để hiển thị các tuỳ chọn có sẵn dành cho câu lệnh import android.support.annotation..

Chạy kiểm tra mã

Để bắt đầu quy trình kiểm tra mã từ Android Studio, bao gồm việc xác thực các chú thích và kiểm tra Lint tự động, hãy chọn Phân tích (Analyze) > Kiểm tra mã (Inspect Code) từ thanh trình đơn. Android Studio hiển thị các thông báo xung đột để gắn cờ các sự cố có thể xảy ra do mã của bạn xung đột với các chú thích, và để đề xuất giải pháp.

Bạn cũng có thể thực thi các chú thích bằng cách sử dụng dòng lệnh để chạy tác vụ lint. Mặc dù cách này có thể hữu ích cho việc gắn cờ sự cố bằng máy chủ tích hợp liên tục, nhưng xin lưu ý rằng tác vụ lint không thực thi các chú thích rỗng (chỉ có Android Studio thực thi). Để biết thêm thông tin về cách bật và chạy các công cụ kiểm tra Lint, hãy xem bài viết Cải thiện mã của bạn bằng Lint.

Lưu ý rằng mặc dù các xung đột chú thích tạo ra cảnh báo, nhưng các cảnh báo này không ngăn việc biên dịch ứng dụng.

Chú thích độ rỗng

Thêm chú thích @Nullable@NonNull để kiểm tra độ rỗng của một biến, tham số hoặc giá trị trả về nhất định. Chú thích @Nullable cho biết một biến, tham số hoặc giá trị trả về có thể có giá trị rỗng trong khi @NonNull cho biết một biến, tham số hoặc giá trị trả về không thể có giá trị rỗng.

Chẳng hạn, nếu một biến cục bộ có chứa giá trị rỗng được chuyển dưới dạng tham số đến một phương thức với chú giải @NonNull đi kèm với tham số đó, thì việc tạo bản dựng bằng mã sẽ tạo ra một cảnh báo cho biết xung đột không rỗng (non-null conflict). Mặt khác, việc cố gắng tham chiếu kết quả của phương thức do @Nullable đánh dấu mà không kiểm tra trước tính chất rỗng của kết quả đó sẽ tạo ra cảnh báo rỗng (nullness warning). Bạn chỉ nên sử dụng @Nullable trên giá trị trả về của một phương thức nếu mọi trường hợp sử dụng phương thức đó đều được đánh dấu rõ ràng là rỗng.

Ví dụ sau đây sẽ đính kèm chú thích @NonNull vào các tham số contextattrs để kiểm tra nhằm đảm bảo rằng các giá trị tham số đã chuyển không phải giá trị rỗng. Chú thích này cũng kiểm tra rằng chính phương thức onCreateView() cũng không trả về giá trị rỗng. Xin lưu ý rằng trong Kotlin chúng ta không cần sử dụng chú thích @NonNull vì chú thích này sẽ được tự động thêm vào mã byte được tạo khi chỉ định một kiểu không thể có giá trị rỗng:

Kotlin

import android.support.annotation.NonNull
...

    /** Add support for inflating the <fragment> tag. **/
    fun onCreateView(
            name: String?,
            context: Context,
            attrs: AttributeSet
    ): View? {
        ...
    }
...

Java

import android.support.annotation.NonNull;
...

    /** Add support for inflating the <fragment> tag. **/
    @NonNull
    @Override
    public View onCreateView(String name, @NonNull Context context,
      @NonNull AttributeSet attrs) {
      ...
      }
...

Phân tích khả năng cho phép rỗng

Android Studio hỗ trợ chạy quy trình phân tích khả năng cho phép rỗng để tự động suy luận và chèn chú thích rỗng trên mã của bạn. Quy trình phân tích khả năng cho phép rỗng sẽ quét các mối liên kết xuyên suốt hệ thống phân cấp phương thức trong mã của bạn để phát hiện:

  • Các phương thức gọi có thể trả về giá trị rỗng
  • Các phương thức không được trả về giá trị rỗng
  • Các biến, chẳng hạn như các trường, các biến cục bộ và các tham số có thể rỗng
  • Các biến, chẳng hạn như các trường, các biến cục bộ, và các tham số không thể chứa giá trị rỗng

Sau đó, quy trình phân tích sẽ tự động chèn các chú thích rỗng thích hợp vào các vị trí được phát hiện.

Để chạy quy trình phân tích khả năng cho phép rỗng (nullability) trong Android Studio, hãy chọn Phân tích (Analyze) >Dự đoán tính chất rỗng (Infer Nullity). Android Studio sẽ chèn các chú thích @Nullable@NonNull của Android tại các vị trí đã phát hiện trong mã của bạn. Sau khi chạy một quy trình phân tích rỗng, bạn nên xác minh lại các chú thích được chèn.

Lưu ý: Khi thêm các chú thích rỗng, tính năng tự động hoàn tất có thể đề xuất các chú thích @Nullable@NotNull của IntelliJ thay vì các chú thích rỗng của Android và có thể tự động nhập thư viện tương ứng. Tuy nhiên, trình kiểm tra Lint của Android Studio chỉ tìm các chú thích giá trị rỗng của Android. Khi xác minh các chú thích, hãy xác nhận rằng dự án của bạn sử dụng chú thích rỗng của Android để trình kiểm tra Lint có thể thông báo đúng cách cho bạn trong quá trình kiểm tra mã.

Chú thích tài nguyên

Việc xác thực các kiểu tài nguyên có thể hữu ích vì Android sẽ tham chiếu đến các tài nguyên (chẳng hạn như các tài nguyên vẽ được và các tài nguyên chuỗi) được chuyển dưới dạng số nguyên. Mã dự kiến tham số tham chiếu đến một loại tài nguyên cụ thể (chẳng hạn các tài nguyên vẽ được) và có thể được chuyển kiểu tham chiếu dự kiến của int, nhưng thực tế lại tham chiếu một loại tài nguyên khác, chẳng hạn như R.string.

Chẳng hạn, thêm các chú thích @StringRes để kiểm tra nhằm đảm bảo rằng tham số tài nguyên chứa tham chiếu R.string, như minh hoạ bên dưới:

Kotlin

abstract fun setTitle(@StringRes resId: Int)

Java

public abstract void setTitle(@StringRes int resId)

Trong quá trình kiểm tra mã, chú thích sẽ tạo cảnh báo nếu một tham chiếu R.string không được chuyển vào tham số.

Bạn có thể thêm các chú thích cho các kiểu tài nguyên khác, chẳng hạn như @DrawableRes, @DimenRes, @ColorRes@InterpolatorRes bằng cách sử dụng cùng một định dạng chú thích và chạy trong quá trình kiểm tra mã. Nếu tham số của bạn hỗ trợ nhiều kiểu tài nguyên, bạn có thể đặt nhiều chú thích trong số này vào một tham số nhất định. Sử dụng @AnyRes để cho biết rằng tham số được chú thích có thể là kiểu tài nguyên R bất kỳ.

Mặc dù bạn có thể sử dụng @ColorRes để chỉ định rằng một tham số phải là tài nguyên màu, nhưng số nguyên màu (ở định dạng RRGGBB hoặc AARRGGBB) không được công nhận là tài nguyên màu. Thay vào đó, hãy sử dụng chú thích @ColorInt để cho biết rằng tham số phải là số nguyên màu (color integer). Các công cụ bản dựng sẽ gắn cờ những đoạn mã không chính xác (chuyển tới các phương thức chú thích các giá trị nhận dạng tài nguyên màu như android.R.color.black thay vì số nguyên màu).

Chú thích luồng

Các chú thích luồng kiểm tra xem một phương thức có được gọi từ một kiểu luồng cụ thể hay không. Các chú thích luồng sau được hỗ trợ:

Lưu ý: Các công cụ bản dựng xem các chú thích @MainThread@UiThread là có thể thay thế cho nhau, vì vậy bạn có thể gọi các phương thức @UiThread từ các phương thức @MainThread, và ngược lại. Tuy nhiên, trong trường hợp ứng dụng hệ thống có nhiều chế độ xem trên các luồng khác nhau, luồng giao diện người dùng có thể khác với luồng chính. Do đó, bạn nên chú thích các phương thức liên kết với hệ phân cấp chế độ xem của ứng dụng bằng @UiThread và chỉ chú thích các phương thức liên kết với vòng đời của ứng dụng bằng @MainThread.

Nếu tất cả các phương thức trong một lớp có cùng yêu cầu về phân luồng thì bạn có thể thêm một chú thích luồng đơn lẻ cho lớp đó để xác minh rằng tất cả các phương thức trong lớp được gọi từ cùng một kiểu luồng.

Một trường hợp sử dụng chú thích luồng phổ biến là xác thực việc ghi đè phương thức trong lớp AsyncTask vì lớp này thực hiện các tác vụ trong nền và chỉ xuất bản kết quả trên chuỗi giao diện người dùng.

Chú thích quy tắc ràng buộc giá trị

Hãy sử dụng chú thích @IntRange, @FloatRange@Size để xác thực giá trị của các tham số đã chuyển. Cả @IntRange@FloatRange đều hữu ích nhất khi được áp dụng cho các tham số mà người dùng có khả năng nhận được sai phạm vi.

Chú thích @IntRange xác thực rằng một giá trị tham số kiểu số nguyên hoặc long nằm trong một phạm vi đã chỉ định. Ví dụ sau đây đảm bảo rằng tham số alpha chứa giá trị số nguyên từ 0 đến 255:

Kotlin

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

Java

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

Chú thích @FloatRange kiểm tra để đảm bảo rằng một giá trị tham số thuộc kiểu số thực hoặc kiểu double nằm trong phạm vi giá trị dấu phẩy động được chỉ định. Ví dụ sau đây đảm bảo rằng tham số alpha chứa giá trị số thực từ 0 đến 1:

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

Chú thích @Size kiểm tra kích thước của một bộ sưu tập hoặc mảng, cũng như độ dài của một chuỗi. Bạn có thể sử dụng chú thích @Size để xác minh các phẩm chất sau:

  • Kích thước tối thiểu (chẳng hạn như @Size(min=2))
  • Kích thước tối đa (chẳng hạn như @Size(max=2))
  • Kích thước chính xác (chẳng hạn như @Size(2))
  • Một giá trị số có kích thước phải là bội số (chẳng hạn như @Size(multiple=2))

Chẳng hạn, @Size(min=1) kiểm tra xem một bộ sưu tập có trống hay không, và @Size(3) xác thực rằng một mảng chứa đúng ba giá trị. Ví dụ sau đây đảm bảo rằng mảng location chứa ít nhất một phần tử:

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

Chú thích quyền

Sử dụng chú thích @RequiresPermission để xác thực quyền của phương thức gọi đối với một phương thức. Để kiểm tra một quyền trong danh sách các quyền hợp lệ, hãy sử dụng thuộc tính anyOf. Để kiểm tra một nhóm quyền, hãy sử dụng thuộc tính allOf. Ví dụ sau đây chú thích phương thức setWallpaper() để đảm bảo rằng phương thức gọi của phương thức này có quyền 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;

Ví dụ này yêu cầu phương thức gọi của phương thức copyImageFile() phải có cả quyền đọc bộ nhớ ngoài và quyền đọc siêu dữ liệu vị trí trong hình ảnh đã sao chép:

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

Để có các quyền đối với ý định, hãy thiết lập yêu cầu về quyền trên trường chuỗi giúp khai báo tên của hành động theo ý định:

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

Để có các quyền đối với nhà cung cấp nội dung mà bạn cần có các quyền riêng biệt để truy cập chức năng đọc và ghi, hãy đóng gói từng yêu cầu cấp quyền trong một chú thích @RequiresPermission.Read hoặc @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");

Quyền gián tiếp

Khi một quyền phụ thuộc vào giá trị cụ thể được cung cấp cho một tham số của phương thức, hãy sử dụng @RequiresPermission trên chính tham số đó mà không liệt kê các quyền cụ thể. Chẳng hạn, phương thức startActivity(Intent) sử dụng quyền gián tiếp đối với ý định được chuyển vào bản thân:

Kotlin

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

Java

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

Khi bạn sử dụng quyền gián tiếp, các công cụ bản dựng sẽ thực hiện việc phân tích luồng dữ liệu để kiểm tra xem đối số đã chuyển vào phương thức này có chú thích @RequiresPermission nào không. Sau đó, các công cụ này thực thi mọi chú thích hiện có từ tham số trong chính phương thức đó. Trong ví dụ startActivity(Intent), các chú giải trong lớp Intent sẽ dẫn đến kết quả là các cảnh báo về việc sử dụng startActivity(Intent) không hợp lệ khi một ý định không có quyền thích hợp được chuyển vào phương thức này, như trong Hình 1.

Hình 1. Cảnh báo được tạo từ một chú thích quyền gián tiếp trên phương thức startActivity(Intent).

Các công cụ bản dựng tạo cảnh báo trên startActivity(Intent) từ chú thích trên tên của hành động theo ý định tương ứng trong lớp Intent:

Kotlin

@SdkConstant(SdkConstantType.ACTIVITY_INTENT_ACTION)
@RequiresPermission(Manifest.permission.CALL_PHONE)
const val ACTION_CALL = "android.intent.action.CALL"

Java

@SdkConstant(SdkConstantType.ACTIVITY_INTENT_ACTION)
@RequiresPermission(Manifest.permission.CALL_PHONE)
public static final String ACTION_CALL = "android.intent.action.CALL";

Nếu cần, bạn có thể thay thế @RequiresPermission cho @RequiresPermission.Read và/hoặc @RequiresPermission.Write khi chú thích một tham số của phương thức. Tuy nhiên, đối với quyền gián tiếp, bạn không nên dùng @RequiresPermission với các chú thích quyền đọc hoặc chú thích quyền ghi.

Chú giải giá trị trả về

Sử dụng chú thích @CheckResult để xác thực rằng kết quả hoặc giá trị trả về của một phương thức thực sự được sử dụng. Thay vì chú thích mọi phương thức không trống (non-void) bằng@CheckResult, hãy thêm chú thích để làm rõ kết quả của các phương thức có thể gây nhầm lẫn. Chẳng hạn, các nhà phát triển Java mới thường nghĩ nhầm rằng <String>.trim() sẽ xoá khoảng trắng khỏi chuỗi ban đầu. Việc chú thích một phương thức bằng các cờ @CheckResult sẽ sử dụng <String>.trim() mà trong đó phương thức gọi không làm gì với giá trị trả về của phương thức đó.

Ví dụ sau đây chú thích phương thức checkPermissions() để đảm bảo giá trị trả về của phương thức đó thực sự được tham chiếu. Ví dụ này cũng đặt tên phương thức enforcePermission() là một phương thức đề xuất dành cho nhà phát triển để sử dụng thay thế:

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

Chú thích CallSuper

Sử dụng chú thích @CallSuper để xác thực rằng phương thức ghi đè sẽ gọi quá trình triển khai cấp cao của phương thức đó. Ví dụ sau đây chú thích phương thức onCreate() để đảm bảo rằng mọi quá trình triển khai phương thức ghi đè sẽ gọi super.onCreate():

Kotlin

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

Java

@CallSuper
protected void onCreate(Bundle savedInstanceState) {
}

Chú thích Typedef

Hãy sử dụng các chú thích @IntDef@StringDef để có thể tạo các chú thích liệt kê của các tập hợp số nguyên và chuỗi dùng để xác thực các kiểu tham chiếu mã khác. Các chú thích typedef đảm bảo rằng một tham số, giá trị trả về hoặc trường cụ thể sẽ tham chiếu đến một tập hợp các hằng số cụ thể. Các chú thích này cũng bật tính năng hoàn thành mã nhằm tự động cung cấp các hằng số được cho phép.

Các chú thích typedef sử dụng @interface để khai báo kiểu chú thích được liệt kê mới. Các chú thích @IntDef@StringDef, cùng với @Retention, chú thích về sự cần thiết phải sử dụng các chú thích mới để khai báo kiểu liệt kê. Chú thích @Retention(RetentionPolicy.SOURCE) yêu cầu trình biên dịch không lưu trữ dữ liệu chú thích được liệt kê trong tệp .class.

Ví dụ sau minh hoạ các bước để tạo chú thích đảm bảo giá trị được chuyển dưới dạng tham số phương thức sẽ tham chiếu đến một trong các hằng số đã khai báo:

Kotlin

import android.support.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 android.support.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);
}

Khi tạo bản dựng từ mã này, một cảnh báo sẽ được tạo nếu tham số mode không tham chiếu đến một trong các hằng số đã khai báo (NAVIGATION_MODE_STANDARD, NAVIGATION_MODE_LIST hoặc NAVIGATION_MODE_TABS).

Bạn cũng có thể kết hợp @IntDef@IntRange để cho biết rằng một số nguyên có thể là một tập hợp các hằng số hoặc một giá trị nhất định trong phạm vi.

Bật tính năng kết hợp các hằng số với cờ

Nếu người dùng có thể kết hợp các hằng số được cho phép với một cờ (chẳng hạn như |, &, ^, v.v.), bạn có thể xác định một chú giải có thuộc tính flag để kiểm tra xem tham số hoặc giá trị trả về có tham chiếu đến một mẫu hợp lệ hay không. Ví dụ sau đây sẽ tạo chú thích DisplayOptions với danh sách các hằng số DISPLAY_ hợp lệ:

Kotlin

import android.support.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 android.support.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 {}

...

Khi bạn tạo mã có cờ chú giải, hệ thống sẽ tạo cảnh báo nếu tham số trang trí hoặc giá trị trả về không tham chiếu đến một mẫu hợp lệ.

Chú thích Keep

Chú thích @Keep đảm bảo rằng lớp hoặc phương thức được chú thích sẽ không bị xoá khi mã được rút gọn tại thời điểm tạo bản dựng. Chú thích này thường được thêm vào các phương thức và các lớp được truy cập thông qua đối tượng phản chiếu (reflection) để ngăn trình biên dịch xem đoạn mã đó là không được sử dụng.

Thận trọng: Các lớp và phương thức mà bạn chú thích bằng @Keep luôn xuất hiện trong tệp APK của ứng dụng, ngay cả khi bạn hoàn toàn không tham chiếu đến các lớp và phương thức này trong logic của ứng dụng.

Để cho ứng dụng luôn ở kích thước nhỏ, hãy cân nhắc xem có cần thiết lưu giữ từng chú thích @Keep trong ứng dụng hay không. Nếu bạn sử dụng phương pháp phản chiếu để truy cập một lớp hoặc phương thức được chú thích, hãy sử dụng một -if có điều kiện trong quy tắc ProGuard để chỉ định các lớp phản chiếu.

Để biết thêm thông tin về cách giảm kích thước mã và chỉ định mã không cần xoá, hãy xem bài viết Thu hẹp mã và tài nguyên của bạn.

Chú giải chế độ hiển thị mã

Hãy sử dụng các chú giải sau để biểu thị chế độ hiển thị của các phần mã cụ thể, chẳng hạn như các phương thức, lớp, trường hoặc gói.

Hiển thị để kiểm thử

Chú thích @VisibleForTesting cho biết rằng một phương thức được chú thích cần phải có mức độ hiển thị nhiều hơn bình thường để bạn có thể kiểm thử phương thức đó. Chú thích này có một đối số otherwise không bắt buộc cho phép bạn chỉ định chế độ hiển thị mà phương thức cần phải có nếu không cần thiết phải hiển thị phương thức đó cho mục đích kiểm thử Lint sử dụng đối số otherwise để thực thi chế độ hiển thị đã dự định.

Trong ví dụ sau, myMethod() thường là private, nhưng trong trường hợp này được gói riêng cho mục đích kiểm thử. Với chỉ định VisibleForTesting.PRIVATE sau đây, công cụ tìm lỗi mã nguồn sẽ hiển thị một thông báo nếu phương thức này được gọi từ bên ngoài ngữ cảnh mà quyền truy cập private cho phép, chẳng hạn như từ một đơn vị biên dịch khác.

Kotlin

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

Java

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

Bạn cũng có thể chỉ định @VisibleForTesting(otherwise = VisibleForTesting.NONE) để cho biết rằng một phương thức chỉ tồn tại trong quá trình kiểm thử. Biểu mẫu chú thích này giống với việc sử dụng @RestrictTo(TESTS). Cả hai đều thực hiện cùng một quy trình kiểm tra mã.

Hạn chế một API

Chú thích @RestrictTo cho biết rằng quyền truy cập vào API được chú thích (gói, lớp hoặc phương thức) bị giới hạn như sau.

Lớp con

Sử dụng biểu mẫu chú thích @RestrictTo(RestrictTo.Scope.SUBCLASSES) để hạn chế chỉ cho phép API truy cập vào các lớp con.

Chỉ những lớp mở rộng lớp được chú thích mới có thể truy cập API này. Công cụ sửa đổi Java protected không hạn chế đầy đủ vì công cụ này cho phép truy cập từ các lớp không liên quan trong cùng một gói. Ngoài ra, có những trường hợp mà bạn muốn để một phương thức ở chế độ public để có sự linh hoạt trong tương lai vì bạn không bao giờ có thể đặt phương thức được protected và ghi đè trước đó ở chế độ public, nhưng bạn muốn cung cấp một gợi ý rằng lớp này chỉ dành cho các mục đích sử dụng trong lớp hoặc từ các lớp con.

Thư viện

Dùng biểu mẫu chú thích @RestrictTo(RestrictTo.Scope.GROUP_ID) để hạn chế quyền truy cập của API vào các thư viện của bạn.

Chỉ mã thư viện của bạn mới có thể truy cập vào API được chú thích. Điều này cho phép bạn không chỉ sắp xếp mã theo bất kỳ hệ thống phân cấp gói nào, mà còn chia sẻ mã giữa một nhóm các thư viện liên quan. Tuỳ chọn này đã có sẵn đối với các thư viện hỗ trợ có nhiều mã triển khai không dành cho mục đích sử dụng bên ngoài, nhưng phải dùng public để chia sẻ mã trên các thư viện hỗ trợ bổ sung.

Lưu ý: Các lớp và gói Thư viện hỗ trợ Android hiện đã được chú thích bằng @RestrictTo(GROUP_ID); nghĩa là nếu bạn vô tình sử dụng các lớp triển khai này, Lint sẽ cảnh báo rằng việc này là không được khuyến khích.

Kiểm thử

Sử dụng biểu mẫu thẻ chú thích @RestrictTo(RestrictTo.Scope.TESTS) để ngăn không cho các nhà phát triển khác truy cập các API đang kiểm thử.

Chỉ mã kiểm thử mới có thể truy cập vào API được chú thích. Chú thích này ngăn các nhà phát triển khác sử dụng các API, vì mục đích phát triển mà bạn dự kiến chỉ là kiểm thử.