การใช้เครื่องมือตรวจสอบโค้ด เช่น lint จะช่วยให้พบปัญหาและปรับปรุงโค้ดได้ แต่เครื่องมือตรวจสอบอาจสรุปข้อมูลได้ไม่มากนัก ตัวอย่างเช่น รหัสทรัพยากร Android ใช้ int
เพื่อระบุสตริง กราฟิก สี และทรัพยากรประเภทอื่นๆ เครื่องมือตรวจสอบจึงไม่สามารถบอกได้ว่าคุณระบุทรัพยากรสตริงในตำแหน่งที่ควรระบุสี สถานการณ์นี้หมายความว่าแอปอาจแสดงผลอย่างไม่ถูกต้องหรือไม่ทำงานเลย แม้ว่าคุณจะใช้การตรวจสอบโค้ดก็ตาม
คําอธิบายประกอบช่วยให้คุณระบุคำแนะนำแก่เครื่องมือตรวจสอบโค้ด เช่น Lint เพื่อช่วยตรวจหาปัญหาโค้ดที่ละเอียดยิ่งขึ้น ระบบจะเพิ่มคำอธิบายประกอบเป็นแท็กข้อมูลเมตาที่คุณแนบกับตัวแปร พารามิเตอร์ และค่าที่แสดงผลเพื่อตรวจสอบค่าที่แสดงผลของเมธอด พารามิเตอร์ที่ส่ง ตัวแปรภายใน และช่อง เมื่อใช้ร่วมกับเครื่องมือตรวจสอบโค้ด คําอธิบายประกอบจะช่วยคุณตรวจหาปัญหาต่างๆ เช่น ข้อยกเว้นเกี่ยวกับ Null Pointer และการทับซ้อนกันของประเภททรัพยากร
Android สนับสนุนคำอธิบายประกอบที่หลากหลายผ่านไลบรารีคำอธิบายประกอบของ Jetpack
คุณสามารถเข้าถึงคลังผ่านแพ็กเกจ androidx.annotation
ได้
หมายเหตุ: หากโมดูลมีการพึ่งพาเครื่องประมวลผลคำอธิบายประกอบ คุณต้องใช้การกำหนดค่าการพึ่งพา kapt
หรือ ksp
สำหรับ Kotlin หรือการกำหนดค่าการพึ่งพา annotationProcessor
สำหรับ Java เพื่อเพิ่มการพึ่งพานั้น
เพิ่มคำอธิบายประกอบลงในโปรเจ็กต์
หากต้องการเปิดใช้คำอธิบายประกอบในโปรเจ็กต์ ให้เพิ่มandroidx.annotation:annotation
ข้อกําหนดในไลบรารีหรือแอป ระบบจะตรวจสอบคำอธิบายประกอบที่คุณเพิ่มเมื่อเรียกใช้การตรวจสอบโค้ดหรืองาน lint
เพิ่มการพึ่งพาไลบรารีคำอธิบายประกอบของ Jetpack
คลังคำอธิบายประกอบของ Jetpack เผยแพร่อยู่ในที่เก็บ Maven ของ Google
ในการเพิ่มไลบรารี Jetpack Anotations ลงในโปรเจ็กต์ ให้ใส่บรรทัดต่อไปนี้ในบล็อก 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 (AAR) ในรูปแบบ XML ในไฟล์ annotations.zip
การเพิ่มข้อกําหนดของ androidx.annotation
จะไม่ทําให้ผู้ใช้ปลายทางของคลังของคุณต้องมีข้อกําหนด
หมายเหตุ: หากใช้ไลบรารี Jetpack อื่นๆ คุณอาจไม่จําเป็นต้องเพิ่มข้อกําหนด androidx.annotation
เนื่องจากไลบรารี Jetpack อื่นๆ จำนวนมากอาศัยไลบรารีคำอธิบายประกอบ คุณจึงอาจมีสิทธิ์เข้าถึงคำอธิบายประกอบอยู่แล้ว
ดูรายการคำอธิบายประกอบทั้งหมดที่รวมอยู่ในที่เก็บ Jetpack ได้ที่ข้อมูลอ้างอิงเกี่ยวกับคลังคำอธิบายประกอบของ Jetpack หรือใช้ฟีเจอร์เติมข้อความอัตโนมัติเพื่อแสดงตัวเลือกที่มีสำหรับคำสั่ง import androidx.annotation.
เรียกใช้การตรวจสอบโค้ด
หากต้องการเริ่มการตรวจสอบโค้ดจาก Android Studio ซึ่งประกอบด้วยการตรวจสอบคำอธิบายประกอบและการตรวจสอบ Lint อัตโนมัติ ให้เลือกวิเคราะห์ > ตรวจสอบโค้ดจากเมนู Android Studio จะแสดงข้อความข้อขัดแย้งเพื่อแจ้งปัญหาที่อาจเกิดขึ้นซึ่งโค้ดขัดแย้งกับคำอธิบายประกอบ และเพื่อแนะนำวิธีแก้ปัญหาที่เป็นไปได้
นอกจากนี้ คุณยังบังคับใช้คำอธิบายประกอบได้โดยเรียกใช้งาน lint
โดยใช้บรรทัดคำสั่ง แม้ว่าวิธีนี้อาจเป็นประโยชน์สำหรับการแจ้งปัญหาเกี่ยวกับเซิร์ฟเวอร์การผสานรวมอย่างต่อเนื่อง แต่งาน lint
จะไม่ได้บังคับใช้คำอธิบายประกอบที่ไม่มีข้อมูล (อธิบายในส่วนต่อไปนี้) มีเพียง Android Studio เท่านั้นที่ดำเนินการเช่นนี้ ดูข้อมูลเพิ่มเติมเกี่ยวกับการเปิดใช้และการเรียกใช้การตรวจสอบ Lint ได้ที่การปรับปรุงโค้ดด้วยการตรวจสอบ Lint
แม้ว่าความขัดแย้งของคำอธิบายประกอบจะทำให้เกิดคำเตือน แต่คำเตือนเหล่านี้จะไม่ป้องกันไม่ให้แอปคอมไพล์
คําอธิบายประกอบเกี่ยวกับค่าว่าง
คําอธิบายประกอบเกี่ยวกับค่า Null อาจมีประโยชน์ในโค้ด Java เพื่อบังคับใช้ว่าค่าจะเป็น Null ได้หรือไม่ แต่จะใช้ในโค้ด Kotlin ได้น้อยลง เนื่องจาก Kotlin มีกฎเกี่ยวกับ Nullability ในตัวซึ่งบังคับใช้ขณะคอมไพล์เพิ่มคำอธิบายประกอบ @Nullable
และ @NonNull
เพื่อตรวจสอบค่า Null ของตัวแปร พารามิเตอร์ หรือค่าที่ส่งกลับ คําอธิบายประกอบ @Nullable
ระบุตัวแปร พารามิเตอร์ หรือค่าที่แสดงผลซึ่งอาจเป็นค่าว่างได้
@NonNull
บ่งบอกถึงตัวแปร พารามิเตอร์ หรือค่าที่ส่งคืนต้องไม่เป็นค่าว่าง
เช่น หากมีการส่งตัวแปรภายในที่มีค่า Null เป็นพารามิเตอร์ไปยังเมธอดที่มีคำอธิบายประกอบ @NonNull
แนบอยู่กับพารามิเตอร์นั้น การสร้างโค้ดจะสร้างคำเตือนที่ระบุข้อขัดแย้งที่ไม่เป็นค่าว่าง นอกจากนี้ การพยายามอ้างอิงผลลัพธ์ของเมธอดที่มีเครื่องหมาย @Nullable
โดยไม่ตรวจสอบก่อนว่าผลลัพธ์เป็น Null หรือไม่ จะทำให้เกิดคำเตือนเกี่ยวกับค่า Null ใช้ @Nullable
กับผลลัพธ์ของเมธอดก็ต่อเมื่อการใช้เมธอดทุกครั้งต้องตรวจสอบค่าว่างอย่างชัดแจ้ง
ตัวอย่างต่อไปนี้แสดงการใช้งานจริงที่เป็นโมฆะ โค้ดตัวอย่าง Kotlin ไม่ได้ใช้ประโยชน์จากแอตทริบิวต์ @NonNull
เนื่องจากระบบจะเพิ่มแอตทริบิวต์ดังกล่าวลงในไบต์โค้ดที่สร้างขึ้นโดยอัตโนมัติเมื่อระบุประเภทที่ไม่ใช่ Null ตัวอย่าง 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 ที่เหมาะสมโดยอัตโนมัติในตำแหน่งที่ตรวจพบ
หากต้องการเรียกใช้การวิเคราะห์ความสามารถในการเว้นว่างใน Android Studio ให้เลือกวิเคราะห์ >
อนุมาน Nullity Android Studio จะแทรกคำอธิบายประกอบ @Nullable
และ @NonNull
ของ Android ในตำแหน่งที่ตรวจพบในโค้ด หลังจากทําการวิเคราะห์ Null แล้ว แนวทางปฏิบัติที่ดีคือยืนยันคำอธิบายประกอบที่แทรก
หมายเหตุ: เมื่อเพิ่มการกำกับเนื้อหาเกี่ยวกับค่า Null ระบบอาจแนะนำการกำกับเนื้อหา
@Nullable
และ @NotNull
ของ IntelliJ แทนการกำกับเนื้อหาเกี่ยวกับค่า Null ของ Android และอาจนำเข้าไลบรารีที่เกี่ยวข้องโดยอัตโนมัติ อย่างไรก็ตาม เครื่องมือตรวจสอบ Lint ของ Android Studio จะมองหาเฉพาะการกำกับเนื้อหา Null ของ Android เมื่อยืนยันคำอธิบายประกอบ ให้ยืนยันว่าโปรเจ็กต์ใช้คำอธิบายประกอบ Android Null เพื่อให้เครื่องมือตรวจสอบ 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 จะแตกต่างจากชุดข้อความหลัก ในกรณีของแอประบบที่มีหลายมุมมองในชุดข้อความที่แตกต่างกัน ดังนั้น คุณควรกำกับเนื้อหาวิธีการที่เชื่อมโยงกับลําดับชั้นมุมมองของแอปด้วย @UiThread
และกำกับเนื้อหาเฉพาะวิธีการที่เชื่อมโยงกับวงจรชีวิตของแอปด้วย @MainThread
หากเมธอดทั้งหมดในคลาสมีข้อกำหนดการแยกชุดข้อความเดียวกัน คุณสามารถเพิ่มคำอธิบายประกอบชุดข้อความเดียวลงในคลาสเพื่อยืนยันว่ามีการเรียกเมธอดทั้งหมดในคลาสจากชุดข้อความประเภทเดียวกัน
การใช้งานทั่วไปของคำอธิบายประกอบเทรดคือการตรวจสอบว่ามีการเรียกใช้เมธอดหรือคลาสที่มีคำอธิบายประกอบด้วย @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)
คําอธิบายประกอบในคลาส Intent
ทําให้เกิดคําเตือนเกี่ยวกับการใช้ startActivity(Intent)
ที่ไม่ถูกต้องเมื่อมีการส่ง Intent ที่ไม่มีสิทธิ์ที่เหมาะสมไปยังเมธอด ดังที่แสดงในรูปที่ 1
เครื่องมือสร้างจะสร้างคำเตือนใน 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
เพื่อตรวจสอบว่าผลลัพธ์หรือค่าที่แสดงผลของเมธอดนั้นๆ ใช้งานได้จริง แทนที่จะกำกับเนื้อหาทุกเมธอดที่ไม่ใช่ void ด้วย @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 โดยระบุคลาสที่เรียกใช้การสะท้อน
ดูข้อมูลเพิ่มเติมเกี่ยวกับวิธีลดขนาดโค้ดและระบุโค้ดที่จะไม่นำออกได้ที่ลดขนาด สร้างความสับสน และเพิ่มประสิทธิภาพแอป
คําอธิบายประกอบระดับการมองเห็นโค้ด
ใช้คำอธิบายประกอบต่อไปนี้เพื่อระบุระดับการเข้าถึงของโค้ดบางส่วน เช่น เมธอด คลาส ฟิลด์ หรือแพ็กเกจ
ทำให้โค้ดแสดงขึ้นสำหรับการทดสอบ
หมายเหตุกำกับ @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 รายการจะดำเนินการตรวจสอบโปรแกรมแก้ไขข้อบกพร่องแบบเดียวกัน
จำกัด API
คําอธิบายประกอบ @RestrictTo
บ่งบอกว่าการเข้าถึง API ที่มีคําอธิบายประกอบ (แพ็กเกจ คลาส หรือเมธอด) ถูกจํากัด ดังนี้
คลาสย่อย
ใช้แบบฟอร์มคำอธิบายประกอบ @RestrictTo(RestrictTo.Scope.SUBCLASSES)
เพื่อจำกัดการเข้าถึง API เฉพาะคลาสย่อยเท่านั้น
มีเพียงคลาสที่ขยายคลาสที่มีคำอธิบายประกอบเท่านั้นที่เข้าถึง API นี้ได้ ตัวแก้ไข protected
ของ Java ไม่จํากัดมากพอ เนื่องจากอนุญาตให้เข้าถึงจากคลาสที่ไม่เกี่ยวข้องภายในแพ็กเกจเดียวกัน นอกจากนี้ มีบางกรณีที่คุณต้องการใช้เมธอด public
เพื่อความยืดหยุ่นในอนาคต เนื่องจากคุณจะไม่สามารถสร้าง protected
ก่อนหน้านี้และเมธอดที่ถูกลบล้าง public
ได้ แต่ต้องการคำแนะนำว่าคลาสนั้นมีไว้สำหรับการใช้งานภายในคลาสหรือจากคลาสย่อยเท่านั้น
ห้องสมุด
ใช้แบบฟอร์มคำอธิบายประกอบ @RestrictTo(RestrictTo.Scope.LIBRARY_GROUP_PREFIX)
เพื่อจำกัดการเข้าถึง API เฉพาะไลบรารีของคุณเท่านั้น
เฉพาะโค้ดไลบรารีของคุณเท่านั้นที่จะเข้าถึง API ที่มีคำอธิบายประกอบได้ ซึ่งจะช่วยให้คุณจัดระเบียบโค้ดในลำดับชั้นของแพ็กเกจที่ต้องการได้ รวมถึงยังแชร์โค้ดกับกลุ่มไลบรารีที่เกี่ยวข้องได้อีกด้วย ตัวเลือกนี้พร้อมใช้งานแล้วสำหรับไลบรารี Jetpack ที่มีโค้ดการใช้งานจำนวนมากซึ่งไม่ได้มีไว้สำหรับการใช้งานภายนอก แต่ต้องpublic
เพื่อแชร์กับไลบรารี Jetpack อื่นๆ ที่เสริมกัน
การทดสอบ
ใช้แบบฟอร์มคำอธิบายประกอบ @RestrictTo(RestrictTo.Scope.TESTS)
เพื่อป้องกันไม่ให้นักพัฒนาแอปรายอื่นเข้าถึง API การทดสอบของคุณ
มีเพียงโค้ดการทดสอบเท่านั้นที่เข้าถึง API ที่มีคำอธิบายประกอบได้ ซึ่งจะป้องกันไม่ให้นักพัฒนาแอปรายอื่นใช้ API สําหรับการพัฒนาที่คุณตั้งใจไว้สําหรับวัตถุประสงค์การทดสอบเท่านั้น