การใช้เครื่องมือตรวจสอบโค้ด เช่น lint จะช่วยให้คุณพบปัญหาและปรับปรุงโค้ดได้ แต่เครื่องมือตรวจสอบจะอนุมานได้เพียงบางส่วนเท่านั้น เช่น รหัสทรัพยากร Android
ใช้ int
เพื่อระบุสตริง กราฟิก สี และทรัพยากรประเภทอื่นๆ
เครื่องมือตรวจสอบจึงไม่สามารถบอกได้ว่าคุณระบุทรัพยากรสตริงในที่ที่คุณควรระบุสี สถานการณ์นี้หมายความว่าแอปอาจแสดงผลไม่ถูกต้องหรือทำงานไม่ได้เลย
แม้ว่าคุณจะใช้การตรวจสอบโค้ดก็ตาม
คำอธิบายประกอบช่วยให้คุณให้คำแนะนำแก่เครื่องมือตรวจสอบโค้ด เช่น Lint เพื่อช่วยตรวจหาปัญหาโค้ดที่ซับซ้อนมากขึ้นเหล่านี้ โดยจะเพิ่มคำอธิบายประกอบเป็นแท็กข้อมูลเมตาที่คุณแนบไปกับตัวแปร พารามิเตอร์ และค่าที่ส่งคืนเพื่อตรวจสอบค่าที่ส่งคืนของเมธอด พารามิเตอร์ที่ส่ง ตัวแปรภายใน และฟิลด์ เมื่อใช้ร่วมกับเครื่องมือตรวจสอบโค้ด คำอธิบายประกอบจะช่วยตรวจหาปัญหาต่างๆ เช่น ข้อยกเว้นของตัวชี้ Null และความขัดแย้งของประเภททรัพยากร
Android รองรับคำอธิบายประกอบที่หลากหลายผ่านไลบรารีคำอธิบายประกอบของ Jetpack
คุณเข้าถึงไลบรารีได้ผ่านแพ็กเกจ
androidx.annotation
หมายเหตุ: หากโมดูลมีข้อกำหนดในการใช้ตัวประมวลผลคำอธิบายประกอบ
คุณต้องใช้การกำหนดค่าการขึ้นต่อกัน kapt
หรือ ksp
สำหรับ Kotlin
หรือการกำหนดค่าการขึ้นต่อกัน annotationProcessor
สำหรับ Java เพื่อเพิ่มการขึ้นต่อกันนั้น
เพิ่มคำอธิบายประกอบลงในโปรเจ็กต์
หากต้องการเปิดใช้คำอธิบายประกอบในโปรเจ็กต์ ให้เพิ่มandroidx.annotation:annotation
การอ้างอิงลงในไลบรารีหรือแอป ระบบจะตรวจสอบคำอธิบายประกอบที่คุณเพิ่มเมื่อคุณเรียกใช้การตรวจสอบโค้ดหรือทาสก์ lint
เพิ่มการพึ่งพาไลบรารี Jetpack Annotations
ระบบจะเผยแพร่ไลบรารีคำอธิบายประกอบ Jetpack ในที่เก็บ Maven ของ Google
หากต้องการเพิ่มไลบรารี Jetpack Annotations ลงในโปรเจ็กต์ ให้ใส่บรรทัดต่อไปนี้
ในบล็อก dependencies
ของไฟล์ build.gradle
หรือ
build.gradle.kts
Kotlin
dependencies { implementation("androidx.annotation:annotation:1.9.1") }
Groovy
dependencies { implementation 'androidx.annotation:annotation:1.9.1' }
หากคุณใช้คำอธิบายประกอบในโมดูลไลบรารีของคุณเอง ระบบจะรวมคำอธิบายประกอบเป็นส่วนหนึ่งของอาร์ติแฟกต์
Android Archive (AAR) ในรูปแบบ XML ในไฟล์ annotations.zip
การเพิ่มการอ้างอิง androidx.annotation
จะไม่ทำให้เกิดการอ้างอิงสำหรับผู้ใช้ปลายทางของไลบรารี
หมายเหตุ: หากใช้ไลบรารี Jetpack อื่นๆ
คุณอาจไม่จำเป็นต้องเพิ่มการขึ้นต่อกันของ androidx.annotation
เนื่องจากไลบรารี Jetpack อื่นๆ อีกมากมายขึ้นอยู่กับไลบรารีคำอธิบายประกอบ คุณจึงอาจมีสิทธิ์เข้าถึง
คำอธิบายประกอบอยู่แล้ว
หากต้องการดูรายการคำอธิบายประกอบทั้งหมดที่รวมอยู่ในที่เก็บ Jetpack โปรดดูการอ้างอิงไลบรารีคำอธิบายประกอบ Jetpack หรือใช้ฟีเจอร์เติมข้อความอัตโนมัติเพื่อแสดงตัวเลือกที่ใช้ได้สำหรับ
คำสั่ง import androidx.annotation.
เรียกใช้การตรวจสอบโค้ด
หากต้องการเริ่มการตรวจสอบโค้ดจาก Android Studio ซึ่งรวมถึงการตรวจสอบความถูกต้องของคำอธิบายประกอบและ การตรวจสอบ Lint อัตโนมัติ ให้เลือกวิเคราะห์ > ตรวจสอบโค้ดจากเมนู Android Studio จะแสดงข้อความแจ้งข้อขัดแย้งเพื่อแจ้งปัญหาที่อาจเกิดขึ้นเมื่อโค้ด ขัดแย้งกับคำอธิบายประกอบ และแนะนำวิธีแก้ไขที่เป็นไปได้
นอกจากนี้ คุณยังบังคับใช้คำอธิบายประกอบได้โดยเรียกใช้
lint
งานโดยใช้บรรทัดคำสั่ง แม้ว่าการดำเนินการนี้อาจมีประโยชน์ในการแจ้งปัญหา
เกี่ยวกับเซิร์ฟเวอร์การผสานรวมอย่างต่อเนื่อง แต่lint
งานจะไม่บังคับใช้คำอธิบายประกอบเกี่ยวกับค่า Null (อธิบายไว้ในส่วนต่อไปนี้) มีเพียง Android Studio เท่านั้นที่ทำเช่นนี้ ดูข้อมูลเพิ่มเติมเกี่ยวกับการเปิดใช้และการเรียกใช้การตรวจสอบ Lint ได้ที่การปรับปรุงโค้ดด้วยการตรวจสอบ Lint
แม้ว่าความขัดแย้งของคำอธิบายประกอบจะทำให้เกิดคำเตือน แต่คำเตือนเหล่านี้ไม่ได้ป้องกันไม่ให้แอปของคุณ คอมไพล์
คำอธิบายประกอบเกี่ยวกับค่า Null
คำอธิบายประกอบเกี่ยวกับค่า Null มีประโยชน์ในโค้ด Java เพื่อบังคับว่าค่าจะเป็น Null ได้หรือไม่ ซึ่งมีประโยชน์น้อยกว่าในโค้ด Kotlin เนื่องจาก Kotlin มีกฎเกี่ยวกับ Nullability ในตัวซึ่งบังคับใช้ในเวลา คอมไพล์เพิ่มคำอธิบายประกอบ @Nullable
และ
@NonNull
เพื่อตรวจสอบค่า Null ของตัวแปร พารามิเตอร์ หรือค่าที่ส่งคืนที่ระบุ @Nullable
หมายเหตุระบุตัวแปร พารามิเตอร์ หรือค่าที่ส่งคืนซึ่งอาจเป็น Null
@NonNull
ระบุตัวแปร พารามิเตอร์ หรือค่าที่ส่งคืนซึ่งต้องไม่เป็น Null
เช่น หากมีการส่งตัวแปรภายในที่มีค่าเป็น Null เป็นพารามิเตอร์ไปยังเมธอด
โดยมีคำอธิบายประกอบ @NonNull
แนบมากับพารามิเตอร์นั้น การสร้างโค้ดจะสร้าง
คำเตือนที่ระบุความขัดแย้งที่ไม่ใช่ Null นอกจากนี้ การพยายามอ้างอิงผลลัพธ์ของเมธอดที่ทำเครื่องหมายด้วย @Nullable
โดยไม่ได้ตรวจสอบก่อนว่าผลลัพธ์เป็น Null หรือไม่ จะทำให้เกิดคำเตือนเกี่ยวกับค่า Null
ใช้ @Nullable
กับค่าที่เมธอดส่งคืน
เฉพาะในกรณีที่ต้องตรวจสอบค่า Null อย่างชัดเจนทุกครั้งที่ใช้เมธอด
ตัวอย่างต่อไปนี้แสดงการทำงานของค่าที่กำหนดให้เป็น Null ได้ โค้ดตัวอย่าง Kotlin ไม่ได้ใช้ประโยชน์จาก
คำอธิบายประกอบ @NonNull
เนื่องจากระบบจะเพิ่มคำอธิบายประกอบนี้ลงในไบต์โค้ดที่สร้างขึ้นโดยอัตโนมัติ
เมื่อระบุประเภทที่กำหนดให้เป็นค่าว่างไม่ได้ ตัวอย่าง Java ใช้ประโยชน์จากคำอธิบายประกอบ @NonNull
ในพารามิเตอร์ context
และ attrs
เพื่อตรวจสอบว่าค่าพารามิเตอร์ที่ส่งผ่าน
ไม่ใช่ค่า Null นอกจากนี้ยังตรวจสอบว่าเมธอด onCreateView()
ไม่ได้แสดงผลเป็น 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) { ... } ...
การวิเคราะห์ความสามารถในการเว้นว่าง
Android Studio รองรับการเรียกใช้การวิเคราะห์ค่า Null เพื่ออนุมานโดยอัตโนมัติ และแทรกคำอธิบายประกอบค่า Null ในโค้ด การวิเคราะห์ค่า Null จะสแกน สัญญาตลอดลำดับชั้นของเมธอดในโค้ดเพื่อตรวจหา
- วิธีการโทรที่อาจแสดงผลเป็น Null
- เมธอดที่ไม่ควรแสดงผลเป็น Null
- ตัวแปร เช่น ฟิลด์ ตัวแปรในเครื่อง และพารามิเตอร์ ที่อาจเป็น null
- ตัวแปร เช่น ฟิลด์ ตัวแปรภายใน และพารามิเตอร์ ที่ไม่สามารถ มีค่า Null
จากนั้นการวิเคราะห์จะแทรกคำอธิบายประกอบค่าว่างที่เหมาะสมในตำแหน่งที่ตรวจพบโดยอัตโนมัติ
หากต้องการเรียกใช้การวิเคราะห์ค่า Null ใน Android Studio ให้เลือกวิเคราะห์ >
อนุมานค่า Null Android Studio จะแทรกคำอธิบายประกอบ @Nullable
และ @NonNull
ของ Android ใน
ตำแหน่งที่ตรวจพบในโค้ด หลังจากเรียกใช้การวิเคราะห์ค่าว่างแล้ว แนวทางปฏิบัติที่ดีคือการยืนยัน
คำอธิบายประกอบที่แทรก
หมายเหตุ: เมื่อเพิ่มคำอธิบายประกอบเกี่ยวกับค่า Null การเติมข้อความอัตโนมัติอาจ
แนะนำคำอธิบายประกอบ
@Nullable
และ
@NotNull
ของ IntelliJ แทนคำอธิบายประกอบเกี่ยวกับค่า Null ของ Android
และอาจนำเข้าไลบรารีที่เกี่ยวข้องโดยอัตโนมัติ อย่างไรก็ตาม เครื่องมือตรวจสอบด้วยเครื่องมือวิเคราะห์ซอร์สโค้ดของ Android Studio
จะมองหาเฉพาะคำอธิบายประกอบ Null ของ Android เท่านั้น เมื่อยืนยันคำอธิบายประกอบ ให้ตรวจสอบว่าโปรเจ็กต์ใช้คำอธิบายประกอบ Null ของ Android เพื่อให้เครื่องมือตรวจสอบ Lint แจ้งเตือนคุณได้อย่างถูกต้องในระหว่างการตรวจสอบโค้ด
คำอธิบายประกอบทรัพยากร
การตรวจสอบประเภททรัพยากรอาจมีประโยชน์เนื่องจาก Android จะส่งการอ้างอิงถึงทรัพยากร เช่น ทรัพยากร drawable และ string เป็นจำนวนเต็ม
โค้ดที่คาดหวังให้พารามิเตอร์อ้างอิงถึงทรัพยากรประเภทใดประเภทหนึ่ง เช่น String
สามารถส่งไปยังประเภทการอ้างอิงที่คาดไว้ของ int
แต่จริงๆ แล้วอ้างอิงถึงทรัพยากรประเภทอื่น
เช่น ทรัพยากร R.string
เช่น เพิ่มคำอธิบายประกอบ @StringRes
เพื่อ
ตรวจสอบว่าพารามิเตอร์ทรัพยากรมีข้อมูลอ้างอิง R.string
หรือไม่ ดังที่แสดงที่นี่
Kotlin
abstract fun setTitle(@StringRes resId: Int)
Java
public abstract void setTitle(@StringRes int resId)
ในระหว่างการตรวจสอบโค้ด คำอธิบายประกอบจะสร้างคำเตือนหากไม่ได้ส่งR.string
การอ้างอิง
ในพารามิเตอร์
คำอธิบายประกอบสำหรับทรัพยากรประเภทอื่นๆ เช่น @DrawableRes
, @DimenRes
, @ColorRes
และ @InterpolatorRes
สามารถเพิ่มได้โดยใช้รูปแบบคำอธิบายประกอบเดียวกันและเรียกใช้ระหว่างการตรวจสอบโค้ด
หากพารามิเตอร์
รองรับทรัพยากรหลายประเภท คุณจะใส่คำอธิบายประกอบทรัพยากรมากกว่า 1 ประเภทในพารามิเตอร์
ที่ต้องการได้ ใช้ @AnyRes
เพื่อระบุว่าพารามิเตอร์ที่อธิบายประกอบอาจเป็นทรัพยากรประเภทใดก็ได้ของ R
แม้ว่าคุณจะใช้ @ColorRes
เพื่อระบุว่าพารามิเตอร์ควรเป็นทรัพยากรสีได้ แต่ระบบจะไม่รู้จักจำนวนเต็มสี (ในรูปแบบ RRGGBB
หรือ AARRGGBB
) เป็นทรัพยากรสี แต่ให้ใช้@ColorInt
คำอธิบายประกอบเพื่อ
ระบุว่าพารามิเตอร์ต้องเป็นจำนวนเต็มสีแทน เครื่องมือบิลด์จะแจ้งโค้ดที่ไม่ถูกต้องซึ่ง
ส่งรหัสทรัพยากรสี เช่น android.R.color.black
แทนที่จะเป็นจำนวนเต็มสี
ไปยังเมธอดที่มีคำอธิบายประกอบ
คำอธิบายประกอบของชุดข้อความ
คำอธิบายประกอบของเธรดจะตรวจสอบว่ามีการเรียกใช้เมธอดจากเธรดประเภทใดประเภทหนึ่งหรือไม่ ระบบรองรับคำอธิบายประกอบในเธรดต่อไปนี้
เครื่องมือบิลด์จะถือว่าคำอธิบายประกอบ @MainThread
และ
@UiThread
ใช้แทนกันได้ คุณจึงเรียกใช้เมธอด @UiThread
จากเมธอด @MainThread
และในทางกลับกันได้ อย่างไรก็ตาม UI
thread อาจแตกต่างจากเทรดหลักได้ในกรณีของแอปของระบบที่มีหลายมุมมอง
ในเทรดต่างๆ ดังนั้น คุณควรใส่คำอธิบายประกอบให้กับเมธอดที่เชื่อมโยงกับลำดับชั้นของมุมมองของแอป
ด้วย @UiThread
และใส่คำอธิบายประกอบให้กับเมธอดที่เชื่อมโยงกับวงจรของแอปเท่านั้นด้วย
@MainThread
หากเมธอดทั้งหมดในคลาสมีข้อกำหนดการแยกเธรดเดียวกัน คุณสามารถเพิ่มคำอธิบายประกอบ single thread ลงในคลาสเพื่อยืนยันว่าเมธอดทั้งหมดในคลาสได้รับการเรียกจากเธรดประเภทเดียวกัน
การใช้งานคำอธิบายประกอบของเธรดโดยทั่วไปคือการตรวจสอบว่าเมธอดหรือคลาสที่มีคำอธิบายประกอบ
@WorkerThread
จะเรียกใช้จากเธรดพื้นหลังที่เหมาะสมเท่านั้น
คำอธิบายประกอบข้อจำกัดของค่า
ใช้คำอธิบายประกอบ @IntRange
,
@FloatRange
และ
@Size
เพื่อ
ตรวจสอบค่าของพารามิเตอร์ที่ส่ง ทั้ง @IntRange
และ @FloatRange
มีประโยชน์มากที่สุดเมื่อใช้กับพารามิเตอร์ที่ผู้ใช้น่าจะระบุช่วงผิด
คำอธิบายประกอบ @IntRange
จะตรวจสอบว่าค่าพารามิเตอร์จำนวนเต็มหรือค่าพารามิเตอร์แบบยาว
อยู่ในช่วงที่ระบุหรือไม่ ตัวอย่างต่อไปนี้ระบุว่าพารามิเตอร์ alpha
ต้องมีค่าจำนวนเต็มตั้งแต่ 0 ถึง 255
Kotlin
fun setAlpha(@IntRange(from = 0, to = 255) alpha: Int) { ... }
Java
public void setAlpha(@IntRange(from=0,to=255) int alpha) { ... }
คำอธิบายประกอบ @FloatRange
จะตรวจสอบว่าค่าพารามิเตอร์ Float หรือ Double
อยู่ภายในช่วงที่ระบุของค่าทศนิยมหรือไม่ ตัวอย่างต่อไปนี้ระบุว่าพารามิเตอร์ alpha
ต้องมีค่าลอยจาก 0.0 ถึง 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) {...}
@Size
คำอธิบายประกอบจะตรวจสอบขนาดของคอลเล็กชันหรือ
อาร์เรย์ หรือความยาวของสตริง คุณใช้คำอธิบายประกอบ @Size
เพื่อยืนยัน
คุณภาพต่อไปนี้ได้
- ขนาดขั้นต่ำ เช่น
@Size(min=2)
- ขนาดสูงสุด เช่น
@Size(max=2)
- ขนาดที่แน่นอน เช่น
@Size(2)
- ตัวเลขที่ขนาดต้องเป็นค่าพหุคูณ เช่น
@Size(multiple=2)
เช่น @Size(min=1)
จะตรวจสอบว่าคอลเล็กชันว่างหรือไม่ และ @Size(3)
จะตรวจสอบว่าอาร์เรย์มีค่า 3 ค่าพอดี
ตัวอย่างต่อไปนี้ระบุว่าอาร์เรย์ location
ต้องมีองค์ประกอบอย่างน้อย 1 รายการ
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); }
คำอธิบายประกอบเกี่ยวกับสิทธิ์
ใช้คำอธิบายประกอบ @RequiresPermission
เพื่อตรวจสอบสิทธิ์ของผู้เรียกใช้เมธอด หากต้องการตรวจสอบสิทธิ์เดียวจากรายการสิทธิ์ที่ถูกต้อง ให้ใช้แอตทริบิวต์ anyOf
หากต้องการตรวจสอบชุดสิทธิ์ ให้ใช้แอตทริบิวต์ allOf
ตัวอย่างต่อไปนี้จะอธิบายประกอบsetWallpaper()
เมธอดเพื่อระบุว่าผู้เรียกเมธอดต้องมีสิทธิ์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;
ตัวอย่างต่อไปนี้กำหนดให้ผู้เรียกใช้เมธอด copyImageFile()
ต้องมีทั้งสิทธิ์อ่านที่จัดเก็บข้อมูลภายนอกและสิทธิ์อ่านข้อมูลเมตาของตำแหน่ง
ในรูปภาพที่คัดลอก
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) { //... }
สำหรับสิทธิ์ใน Intent ให้วางข้อกำหนดด้านสิทธิ์ในฟิลด์สตริงที่กำหนด ชื่อการดำเนินการของ 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";
สำหรับสิทธิ์ในผู้ให้บริการเนื้อหาที่ต้องมีสิทธิ์แยกต่างหากสำหรับการเข้าถึงแบบอ่านและเขียน
ให้รวมข้อกำหนดสิทธิ์แต่ละรายการไว้ในคำอธิบายประกอบ @RequiresPermission.Read
หรือ @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");
สิทธิ์โดยอ้อม
เมื่อสิทธิ์ขึ้นอยู่กับค่าที่เฉพาะเจาะจงซึ่งระบุไว้ในพารามิเตอร์ของเมธอด ให้ใช้
@RequiresPermission
ในพารามิเตอร์นั้นโดยไม่ต้องแสดงรายการสิทธิ์ที่เฉพาะเจาะจง
เช่น เมธอด startActivity(Intent)
ใช้วิธีการให้สิทธิ์โดยอ้อมใน Intent ที่ส่งไปยังเมธอด
Kotlin
abstract fun startActivity(@RequiresPermission intent: Intent, bundle: Bundle?)
Java
public abstract void startActivity(@RequiresPermission Intent intent, @Nullable Bundle)
เมื่อใช้สิทธิ์โดยอ้อม เครื่องมือบิลด์จะทำการวิเคราะห์การไหลของข้อมูลเพื่อตรวจสอบว่าอาร์กิวเมนต์ที่ส่งไปยังเมธอดมีคำอธิบายประกอบ @RequiresPermission
หรือไม่ จากนั้นจะ
บังคับใช้คำอธิบายประกอบที่มีอยู่จากพารามิเตอร์ในเมธอดเอง ในstartActivity(Intent)
ตัวอย่าง
startActivity(Intent)
คำอธิบายประกอบในคลาส Intent
ทำให้เกิดคำเตือนที่ได้
จากการใช้ startActivity(Intent)
อย่างไม่ถูกต้องเมื่อมีการส่ง Intent ที่ไม่มีสิทธิ์ที่เหมาะสม
ไปยังเมธอด ดังที่แสดงในรูปที่ 1

รูปที่ 1 คำเตือนที่สร้างขึ้นจากคำอธิบายประกอบสิทธิ์โดยอ้อม
ในเมธอด startActivity(Intent)
เครื่องมือบิลด์จะสร้างคำเตือนใน startActivity(Intent)
จากคำอธิบายประกอบ
ในชื่อการดำเนินการของ Intent ที่เกี่ยวข้องในคลาส 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";
หากจำเป็น คุณสามารถแทนที่ @RequiresPermission
ด้วย
@RequiresPermission.Read
หรือ @RequiresPermission.Write
เมื่อใส่คำอธิบายประกอบ
พารามิเตอร์ของเมธอด อย่างไรก็ตาม สำหรับสิทธิ์โดยอ้อม @RequiresPermission
ไม่ควรใช้ร่วมกับคำอธิบายประกอบสิทธิ์อ่านหรือสิทธิ์เขียน
คำอธิบายประกอบค่าที่ส่งคืน
ใช้คำอธิบายประกอบ @CheckResult
เพื่อ
ตรวจสอบว่ามีการใช้ผลลัพธ์หรือค่าที่ส่งคืนของเมธอดจริง แทนที่จะใส่คำอธิบายประกอบ @CheckResult
ในทุกเมธอดที่ไม่เป็นโมฆะ ให้ใส่คำอธิบายประกอบเพื่อชี้แจงผลลัพธ์ของเมธอดที่อาจทำให้เกิดความสับสน
ตัวอย่างเช่น นักพัฒนาซอฟต์แวร์ Java มือใหม่มักจะเข้าใจผิดว่า
<String>.trim()
จะนำช่องว่างออกจากสตริงเดิม การใส่คำอธิบายประกอบ
เมธอดด้วยแฟล็ก @CheckResult
จะใช้ <String>.trim()
เมื่อผู้เรียกไม่ได้ทำอะไรกับค่าที่แสดงของเมธอด
ตัวอย่างต่อไปนี้จะอธิบายcheckPermissions()
เมธอดเพื่อตรวจสอบว่ามีการอ้างอิงค่าที่ส่งคืนของเมธอด
จริงหรือไม่ นอกจากนี้ ยังระบุenforcePermission()
เมธอดเป็นเมธอดที่จะแนะนำให้นักพัฒนาแอปใช้แทนด้วย
Kotlin
@CheckResult(suggest = "#enforcePermission(String,int,int,String)") abstract fun checkPermission(permission: String, pid: Int, uid: Int): Int
Java
@CheckResult(suggest="#enforcePermission(String,int,int,String)") public abstract int checkPermission(@NonNull String permission, int pid, int uid);
คำอธิบายประกอบ CallSuper
ใช้คำอธิบายประกอบ @CallSuper
เพื่อ
ตรวจสอบว่าเมธอดที่ลบล้างเรียกใช้การติดตั้งใช้งานระดับบนสุดของเมธอด
ตัวอย่างต่อไปนี้
อธิบายประกอบเมธอด onCreate()
เพื่อให้มั่นใจว่าการติดตั้งใช้งานเมธอดที่ลบล้าง
จะเรียกใช้ super.onCreate()
Kotlin
@CallSuper override fun onCreate(savedInstanceState: Bundle?) { }
Java
@CallSuper protected void onCreate(Bundle savedInstanceState) { }
คำอธิบายประกอบ Typedef
คำอธิบายประกอบ Typedef จะตรวจสอบว่าพารามิเตอร์ ค่าที่แสดงผล หรือฟิลด์อ้างอิงชุดค่าคงที่ที่เฉพาะเจาะจงหรือไม่ นอกจากนี้ยังเปิดใช้การเติมโค้ดโดยอัตโนมัติ เพื่อแสดงค่าคงที่ที่อนุญาต
ใช้คำอธิบายประกอบ @IntDef
และ
@StringDef
เพื่อสร้างคำอธิบายประกอบแบบแจงนับของชุดจำนวนเต็มและสตริงเพื่อตรวจสอบการอ้างอิงโค้ดประเภทอื่นๆ
คำอธิบายประกอบ Typedef ใช้ @interface
เพื่อประกาศประเภทคำอธิบายประกอบที่แจงนับใหม่
คำอธิบายประกอบ @IntDef
และ @StringDef
พร้อมกับ
@Retention
จะใส่คำอธิบายประกอบใหม่ และจำเป็นต่อการกำหนด
ประเภทที่แจงนับ @Retention(RetentionPolicy.SOURCE)
คำอธิบายประกอบจะบอกคอมไพเลอร์
ไม่ให้จัดเก็บข้อมูลคำอธิบายประกอบที่แจงนับไว้ในไฟล์ .class
ตัวอย่างต่อไปนี้แสดงขั้นตอนในการสร้างคำอธิบายประกอบที่ตรวจสอบว่าค่าที่ส่งผ่าน เป็นพารามิเตอร์ของเมธอดอ้างอิงค่าคงที่ที่กำหนดไว้ค่าใดค่าหนึ่งหรือไม่
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); }
เมื่อสร้างโค้ดนี้ ระบบจะสร้างคำเตือนหากพารามิเตอร์ mode
ไม่ได้อ้างอิงค่าคงที่ที่กำหนดไว้ค่าใดค่าหนึ่ง (NAVIGATION_MODE_STANDARD
, NAVIGATION_MODE_LIST
หรือ NAVIGATION_MODE_TABS
)
รวม @IntDef
และ @IntRange
เพื่อระบุว่าจำนวนเต็มอาจเป็นชุดค่าคงที่ที่กำหนดหรือค่าภายในช่วง
เปิดใช้การรวมค่าคงที่กับ Flag
หากผู้ใช้สามารถรวมค่าคงที่ที่อนุญาตกับแฟล็ก (เช่น |
, &
, ^
และอื่นๆ) คุณจะกำหนดคำอธิบายประกอบที่มีแอตทริบิวต์ flag
เพื่อตรวจสอบว่าพารามิเตอร์หรือค่าที่ส่งคืนอ้างอิงรูปแบบที่ถูกต้องหรือไม่
ตัวอย่างต่อไปนี้สร้างคำอธิบายประกอบ DisplayOptions
พร้อมรายการค่าคงที่ 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 {} ...
เมื่อสร้างโค้ดด้วยแฟล็กคำอธิบายประกอบ ระบบจะสร้างคำเตือนหากพารามิเตอร์ที่ตกแต่ง หรือค่าที่ส่งคืนไม่ได้อ้างอิงรูปแบบที่ถูกต้อง
เก็บคำอธิบายประกอบ
@Keep
คำอธิบายประกอบช่วยให้มั่นใจได้ว่าจะไม่มีการนำคลาสหรือเมธอดที่มีคำอธิบายประกอบออกเมื่อมีการลดขนาดโค้ด
ในเวลาบิลด์ โดยปกติแล้ว ระบบจะเพิ่มคำอธิบายประกอบนี้
ในเมธอดและคลาสที่เข้าถึงผ่านการสะท้อนเพื่อป้องกันไม่ให้คอมไพเลอร์
ถือว่าโค้ดไม่ได้ใช้งาน
ข้อควรระวัง: คลาสและเมธอดที่คุณใส่คำอธิบายประกอบ
โดยใช้ @Keep
จะปรากฏใน APK ของแอปเสมอ แม้ว่าคุณจะไม่เคย
อ้างอิงคลาสและเมธอดเหล่านี้ภายในตรรกะของแอปก็ตาม
หากต้องการให้แอปมีขนาดเล็ก ให้พิจารณาว่าจำเป็นต้องเก็บรักษา
@Keep
คำอธิบายประกอบแต่ละรายการในแอปหรือไม่ หากใช้การสะท้อนเพื่อ
เข้าถึงคลาสหรือเมธอดที่มีคำอธิบายประกอบ ให้ใช้เงื่อนไข
-if
ในกฎ ProGuard โดยระบุคลาส
ที่ทำการเรียกการสะท้อน
ดูข้อมูลเพิ่มเติมเกี่ยวกับวิธีลดขนาดโค้ดและระบุโค้ดที่จะไม่นำออกได้ที่ลดขนาด ปรับให้ยากต่อการอ่าน (Obfuscate) และเพิ่มประสิทธิภาพแอป
คำอธิบายประกอบเกี่ยวกับการแสดงโค้ด
ใช้คำอธิบายประกอบต่อไปนี้เพื่อระบุระดับการมองเห็นของโค้ดบางส่วน เช่น เมธอด คลาส ฟิลด์ หรือแพ็กเกจ
ทำให้โค้ดมองเห็นได้สำหรับการทดสอบ
@VisibleForTesting
คำอธิบายประกอบระบุว่าเมธอดที่มีคำอธิบายประกอบจะมองเห็นได้มากกว่าปกติที่จำเป็นต่อการทำให้เมธอด
ทดสอบได้ คำอธิบายประกอบนี้มีอาร์กิวเมนต์ otherwise
ที่ไม่บังคับซึ่งช่วยให้คุณ
กำหนดระดับการมองเห็นของเมธอดได้หากไม่จำเป็นต้องทำให้มองเห็นได้
สำหรับการทดสอบ Lint ใช้อาร์กิวเมนต์ otherwise
เพื่อบังคับใช้ระดับการมองเห็นที่ต้องการ
ในตัวอย่างต่อไปนี้ โดยปกติแล้ว myMethod()
จะเป็น private
แต่จะเป็น package-private
สำหรับการทดสอบ เมื่อใช้การกำหนด VisibleForTesting.PRIVATE
Lint จะแสดงข้อความหากมีการเรียกใช้เมธอดนี้จากภายนอกบริบท
ที่อนุญาตโดยการเข้าถึง private
เช่น จากหน่วยการคอมไพล์อื่น
Kotlin
@VisibleForTesting(otherwise = VisibleForTesting.PRIVATE) fun myMethod() { ... }
Java
@VisibleForTesting(otherwise = VisibleForTesting.PRIVATE) void myMethod() { ... }
นอกจากนี้ คุณยังระบุ @VisibleForTesting(otherwise = VisibleForTesting.NONE)
เพื่อระบุว่ามีเมธอดสำหรับการทดสอบเท่านั้น แบบฟอร์มนี้เหมือนกับการใช้
@RestrictTo(TESTS)
ทั้ง 2 คำสั่งจะทำการตรวจสอบ Lint เหมือนกัน
จำกัด API
คำอธิบายประกอบ @RestrictTo
ระบุว่าการเข้าถึง API ที่มีคำอธิบายประกอบ (แพ็กเกจ คลาส หรือเมธอด) ถูกจำกัด
ดังนี้
คลาสย่อย
ใช้แบบฟอร์มคำอธิบายประกอบ @RestrictTo(RestrictTo.Scope.SUBCLASSES)
เพื่อจำกัด
การเข้าถึง API ให้เฉพาะคลาสย่อย
เฉพาะคลาสที่ขยายคลาสที่มีคำอธิบายประกอบเท่านั้นที่จะเข้าถึง API นี้ได้ ตัวแก้ไข Java
protected
มีข้อจำกัดไม่เพียงพอ เนื่องจากอนุญาตให้เข้าถึง
จากคลาสที่ไม่เกี่ยวข้องภายในแพ็กเกจเดียวกัน นอกจากนี้ ยังมีกรณีที่คุณต้องการปล่อยให้เมธอด public
เป็น protected
และเมธอดที่ลบล้าง public
ไว้เพื่อความยืดหยุ่นในอนาคต เนื่องจากคุณไม่สามารถทำให้เมธอดก่อนหน้านี้เป็น protected
ได้ แต่คุณต้องการให้คำแนะนำว่าคลาสนี้มีไว้สำหรับการใช้งานภายในคลาสหรือจากคลาสย่อยเท่านั้น
ห้องสมุด
ใช้แบบฟอร์มคำอธิบายประกอบ @RestrictTo(RestrictTo.Scope.LIBRARY_GROUP_PREFIX)
เพื่อ
จำกัดการเข้าถึง API ให้เฉพาะไลบรารีของคุณ
เฉพาะรหัสไลบรารีเท่านั้นที่เข้าถึง API ที่มีคำอธิบายประกอบได้ ซึ่งไม่เพียงช่วยให้คุณจัดระเบียบโค้ด
ในลำดับชั้นของแพ็กเกจที่ต้องการได้เท่านั้น แต่ยังช่วยให้คุณแชร์
โค้ดในกลุ่มไลบรารีที่เกี่ยวข้องได้อีกด้วย ตัวเลือกนี้มีให้ใช้งานแล้วในไลบรารี Jetpack
ซึ่งมีโค้ดการติดตั้งใช้งานจำนวนมากที่ไม่ได้มีไว้สำหรับการใช้งานภายนอก แต่ต้องpublic
เพื่อแชร์ในไลบรารี Jetpack ที่หลากหลายซึ่งเสริมกัน
การทดสอบ
ใช้แบบฟอร์มคำอธิบายประกอบ @RestrictTo(RestrictTo.Scope.TESTS)
เพื่อป้องกันไม่ให้นักพัฒนาแอปรายอื่นเข้าถึง API สำหรับการทดสอบของคุณ
เฉพาะโค้ดทดสอบเท่านั้นที่เข้าถึง API ที่มีคำอธิบายประกอบได้ ซึ่งจะช่วยป้องกันไม่ให้นักพัฒนาแอปรายอื่น ใช้ API สำหรับการพัฒนาที่คุณตั้งใจไว้เพื่อการทดสอบเท่านั้น