การใช้เครื่องมือตรวจสอบโค้ด เช่น Lint จะช่วยคุณค้นหา
ปัญหาและปรับปรุงโค้ดได้ แต่เครื่องมือตรวจสอบจะอนุมานได้เพียงบางส่วนเท่านั้น เช่น รหัสทรัพยากร Android ใช้ int เพื่อระบุสตริง กราฟิก สี และทรัพยากรประเภทอื่นๆ ดังนั้นเครื่องมือตรวจสอบจึงไม่สามารถบอกได้ว่าคุณระบุทรัพยากรสตริงในที่ที่คุณควรระบุสี สถานการณ์นี้หมายความว่าแอปของคุณอาจแสดงผลไม่ถูกต้องหรือทำงานไม่ได้เลย แม้ว่าคุณจะใช้การตรวจสอบโค้ดก็ตาม
คำอธิบายประกอบช่วยให้คุณให้คำแนะนำแก่เครื่องมือตรวจสอบโค้ด เช่น Lint เพื่อช่วยตรวจหาปัญหาโค้ดที่ซับซ้อนมากขึ้น โดยคำอธิบายประกอบจะเพิ่มเป็นแท็กข้อมูลเมตาที่คุณแนบกับตัวแปร พารามิเตอร์ และค่าที่แสดงผลเพื่อตรวจสอบค่าที่แสดงผลของเมธอด พารามิเตอร์ที่ส่ง ตัวแปรเฉพาะที่ และฟิลด์ เมื่อใช้กับเครื่องมือตรวจสอบโค้ด คำอธิบายประกอบจะช่วยคุณตรวจหาปัญหาต่างๆ เช่น null pointer exception และความขัดแย้งของประเภททรัพยากร
Android รองรับคำอธิบายประกอบที่หลากหลายผ่าน
ไลบรารีคำอธิบายประกอบ Jetpack.
คุณสามารถเข้าถึงไลบรารีผ่านแพ็กเกจ androidx.annotation
หมายเหตุ: หากโมดูลมีการพึ่งพิงโปรเซสเซอร์สำหรับคำอธิบายประกอบ คุณต้องใช้การกำหนดค่าทรัพยากร Dependency kapt หรือ ksp สำหรับ Kotlin หรือการกำหนดค่าทรัพยากร Dependency annotationProcessor สำหรับ Java เพื่อเพิ่มทรัพยากร Dependency ดังกล่าว
เพิ่มคำอธิบายประกอบลงในโปรเจ็กต์
หากต้องการเปิดใช้คำอธิบายประกอบในโปรเจ็กต์ ให้เพิ่มทรัพยากร Dependency androidx.annotation:annotation ลงในไลบรารีหรือแอป ระบบจะตรวจสอบคำอธิบายประกอบที่คุณเพิ่มเมื่อคุณเรียกใช้การตรวจสอบโค้ดหรืองาน lint
เพิ่มทรัพยากร Dependency ของไลบรารีคำอธิบายประกอบ Jetpack
ไลบรารีคำอธิบายประกอบ Jetpack เผยแพร่ใน
ที่เก็บ Maven ของ Google
หากต้องการเพิ่มไลบรารีคำอธิบายประกอบ Jetpack ลงในโปรเจ็กต์ ให้ใส่บรรทัดต่อไปนี้
ในบล็อก dependencies ของไฟล์ build.gradle หรือ
build.gradle.kts
Kotlin
dependencies { implementation("androidx.annotation:annotation:1.10.0") }
ดึงดูด
dependencies { implementation 'androidx.annotation:annotation:1.10.0' }
หากคุณใช้คำอธิบายประกอบในโมดูลไลบรารีของคุณเอง ระบบจะรวมคำอธิบายประกอบเป็นส่วนหนึ่งของอาร์ติแฟกต์ Android Archive (AAR) ในรูปแบบ XML ในไฟล์ annotations.zip การเพิ่มการพึ่งพิง androidx.annotation จะไม่ทำให้เกิดการพึ่งพิงสำหรับผู้ใช้ปลายทางของไลบรารี
หมายเหตุ: หากคุณใช้ไลบรารี Jetpack อื่นๆ คุณอาจไม่จำเป็นต้องเพิ่มทรัพยากร Dependency androidx.annotation เนื่องจากไลบรารี Jetpack อื่นๆ จำนวนมากพึ่งพิงไลบรารีคำอธิบายประกอบ คุณจึงอาจมีสิทธิ์เข้าถึงคำอธิบายประกอบอยู่แล้ว
หากต้องการดูรายการคำอธิบายประกอบทั้งหมดที่รวมอยู่ในที่เก็บ Jetpack ให้ดูข้อมูลอ้างอิง
ไลบรารีคำอธิบายประกอบ Jetpack หรือใช้ฟีเจอร์เติมข้อความอัตโนมัติเพื่อแสดงตัวเลือกที่ใช้ได้สำหรับคำสั่ง
import androidx.annotation.
เรียกใช้การตรวจสอบโค้ด
หากต้องการเริ่มการตรวจสอบโค้ดจาก Android Studio ซึ่งรวมถึงการตรวจสอบคำอธิบายประกอบและการตรวจสอบ Lint อัตโนมัติ ให้เลือกวิเคราะห์ > ตรวจสอบโค้ด จากเมนู Android Studio จะแสดงข้อความความขัดแย้งเพื่อแจ้งปัญหาที่อาจเกิดขึ้นซึ่งโค้ดของคุณขัดแย้งกับคำอธิบายประกอบ และแนะนำวิธีแก้ไขที่เป็นไปได้
นอกจากนี้ คุณยังบังคับใช้คำอธิบายประกอบได้โดย เรียกใช้งาน
lint โดยใช้บรรทัดคำสั่ง แม้ว่าวิธีนี้อาจมีประโยชน์ในการแจ้งปัญหาเกี่ยวกับเซิร์ฟเวอร์การรวมอย่างต่อเนื่อง แต่งาน lint จะไม่บังคับใช้คำอธิบายประกอบ Nullness (อธิบายไว้ในส่วนถัดไป) ซึ่งมีเพียง Android Studio เท่านั้นที่ทำได้ ดูข้อมูลเพิ่มเติมเกี่ยวกับการเปิดใช้และการเรียกใช้การตรวจสอบ Lint
ได้ที่ หัวข้อการปรับปรุงโค้ดโดยใช้ Lint
ตรวจสอบ
แม้ว่าความขัดแย้งของคำอธิบายประกอบจะสร้างคำเตือน แต่คำเตือนเหล่านี้จะไม่ทำให้แอปคอมไพล์ไม่ได้
คำอธิบายประกอบ Nullness
คำอธิบายประกอบ Nullness อาจมีประโยชน์ในโค้ด Java เพื่อบังคับใช้ว่าค่าสามารถเป็น Null ได้หรือไม่ แต่คำอธิบายประกอบ Nullness จะมีประโยชน์น้อยกว่าในโค้ด Kotlin เนื่องจาก Kotlin มีกฎความสามารถในการเว้นว่างในตัวที่บังคับใช้ในเวลาคอมไพล์เพิ่มคำอธิบายประกอบ @Nullable และ @NonNull เพื่อตรวจสอบ Nullness ของตัวแปร พารามิเตอร์ หรือค่าที่แสดงผลที่ระบุ คำอธิบายประกอบ @Nullable ระบุตัวแปร พารามิเตอร์ หรือค่าที่แสดงผลที่สามารถเป็น Null ได้
@NonNull ระบุตัวแปร พารามิเตอร์ หรือค่าที่แสดงผลที่ไม่สามารถเป็น Null ได้
ตัวอย่างเช่น หากมีการส่งตัวแปรเฉพาะที่ที่มีค่า Null เป็นพารามิเตอร์ไปยังเมธอดที่มีคำอธิบายประกอบ @NonNull แนบอยู่กับพารามิเตอร์นั้น การสร้างโค้ดจะสร้างคำเตือนที่ระบุความขัดแย้งที่ไม่ใช่ Null นอกจากนี้ การพยายามอ้างอิงผลลัพธ์ของเมธอดที่ทำเครื่องหมายด้วย @Nullable โดยไม่ได้ตรวจสอบก่อนว่าผลลัพธ์เป็น Null หรือไม่ จะสร้างคำเตือน Nullness ใช้ @Nullable กับค่าที่แสดงผลของเมธอดก็ต่อเมื่อการใช้เมธอดทุกครั้งต้องมีการตรวจสอบ Null อย่างชัดเจน
ตัวอย่างต่อไปนี้แสดงความสามารถในการเว้นว่างในการทำงาน โค้ดตัวอย่าง 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) { ... } ...
การวิเคราะห์ Nullability
Android Studio รองรับการเรียกใช้การวิเคราะห์ความสามารถในการเว้นว่าง เพื่ออนุมาน และแทรกคำอธิบายประกอบ Nullness ในโค้ดของคุณโดยอัตโนมัติ การวิเคราะห์ความสามารถในการเว้นว่าง จะสแกน สัญญาตลอดลำดับชั้นของเมธอดในโค้ดเพื่อตรวจหาสิ่งต่อไปนี้
- การเรียกเมธอดที่แสดงผล Null ได้
- เมธอดที่ไม่ควรแสดงผล Null
- ตัวแปร เช่น ฟิลด์ ตัวแปรเฉพาะที่ และพารามิเตอร์ที่สามารถเป็น Null ได้
- ตัวแปร เช่น ฟิลด์ ตัวแปรเฉพาะที่ และพารามิเตอร์ที่ไม่สามารถ เก็บค่า Null ได้
จากนั้นการวิเคราะห์จะแทรกคำอธิบายประกอบ Null ที่เหมาะสมใน ตำแหน่งที่ตรวจพบโดยอัตโนมัติ
หากต้องการเรียกใช้การวิเคราะห์ Nullness ใน Android Studio ให้เลือกวิเคราะห์ > อนุมาน Nullness Android Studio จะแทรกคำอธิบายประกอบ @Nullable และ @NonNull ของ Android ใน
ตำแหน่งที่ตรวจพบในโค้ด หลังจากเรียกใช้การวิเคราะห์ Null แล้ว แนวทางปฏิบัติที่ดีคือการตรวจสอบคำอธิบายประกอบที่แทรก
หมายเหตุ: เมื่อเพิ่มคำอธิบายประกอบ Nullness การเติมข้อความอัตโนมัติอาจ
แนะนำคำอธิบายประกอบ IntelliJ
@Nullable และ
@NotNull แทนคำอธิบายประกอบ Null ของ Android
และอาจนำเข้าไลบรารีที่เกี่ยวข้องโดยอัตโนมัติ อย่างไรก็ตาม ตัวตรวจสอบ Lint ของ Android Studio
จะมองหาเฉพาะคำอธิบายประกอบ Null ของ Android เท่านั้น เมื่อตรวจสอบคำอธิบายประกอบ ให้ยืนยันว่าโปรเจ็กต์ใช้คำอธิบายประกอบ Null ของ Android เพื่อให้ตัวตรวจสอบ Lint แจ้งให้คุณทราบอย่างเหมาะสมระหว่างการตรวจสอบโค้ด
คำอธิบายประกอบทรัพยากร
การตรวจสอบประเภททรัพยากรอาจมีประโยชน์เนื่องจากข้อมูลอ้างอิงทรัพยากรของ Android เช่น ทรัพยากร Drawable และ สตริง จะส่งเป็นจำนวนเต็ม
โค้ดที่คาดหวังให้พารามิเตอร์อ้างอิงทรัพยากรประเภทหนึ่งๆ เช่น 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 แทนจำนวนเต็มสี ไปยังเมธอดที่มีคำอธิบายประกอบ
คำอธิบายประกอบ Thread
คำอธิบายประกอบ Thread จะตรวจสอบว่ามีการเรียกเมธอดจาก Thread ประเภทใดประเภทหนึ่งหรือไม่ ระบบรองรับคำอธิบายประกอบ Thread ต่อไปนี้
เครื่องมือบิลด์จะถือว่าคำอธิบายประกอบ @MainThread และ @UiThread ใช้แทนกันได้ ดังนั้นคุณจึงเรียกเมธอด @UiThread จากเมธอด @MainThread และในทางกลับกันได้ อย่างไรก็ตาม Thread UI อาจแตกต่างจาก Thread หลักในกรณีของแอปของระบบที่มีหลายมุมมองใน Thread ต่างๆ ดังนั้น คุณควรใส่คำอธิบายประกอบ @UiThread ให้กับเมธอดที่เชื่อมโยงกับลำดับชั้นการแสดงผลของแอป และใส่คำอธิบายประกอบ @MainThread ให้กับเมธอดที่เชื่อมโยงกับวงจรของแอปเท่านั้น
หากเมธอดทั้งหมดในคลาสมีข้อกำหนดการทำงานแบบมัลติเธรดเหมือนกัน คุณสามารถเพิ่มคำอธิบายประกอบ Thread เดียวลงในคลาสเพื่อยืนยันว่ามีการเรียกเมธอดทั้งหมดในคลาสจาก Thread ประเภทเดียวกัน
การใช้คำอธิบายประกอบ Thread ที่พบบ่อยคือการตรวจสอบว่ามีการเรียกเมธอดหรือคลาสที่มีคำอธิบายประกอบ
@WorkerThread จาก Thread เบื้องหลังที่เหมาะสมเท่านั้น
คำอธิบายประกอบข้อจำกัดค่า
ใช้คำอธิบายประกอบ @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 ต้องมีค่า Float ตั้งแต่ 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
รูปที่ 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 ให้กับเมธอดที่ไม่ใช่ Void ทุกเมธอด ให้เพิ่มคำอธิบายประกอบเพื่อชี้แจงผลลัพธ์ของเมธอดที่อาจทำให้เกิดความสับสน
ตัวอย่างเช่น นักพัฒนาซอฟต์แวร์ 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 เพื่อตรวจสอบว่าพารามิเตอร์หรือค่าที่แสดงผลอ้างอิงรูปแบบที่ถูกต้องหรือไม่
ตัวอย่างต่อไปนี้สร้างคำอธิบายประกอบ 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 ช่วยให้มั่นใจได้ว่าจะไม่มีการนำคลาสหรือเมธอดที่มีคำอธิบายประกอบออกเมื่อมีการลดขนาดโค้ดในเวลาบิลด์ โดยปกติแล้วจะมีการเพิ่มคำอธิบายประกอบนี้ลงในเมธอดและคลาสที่เข้าถึงผ่านการสะท้อนเพื่อป้องกันไม่ให้คอมไพลเลอร์ถือว่าโค้ดไม่ได้ใช้งาน
ข้อควรระวัง: คลาสและเมธอดที่คุณใส่คำอธิบายประกอบ
โดยใช้ @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 รูปแบบจะทำการตรวจสอบ Lint เหมือนกัน
จำกัด API
คำอธิบายประกอบ @RestrictTo
ระบุว่าการเข้าถึง API (แพ็กเกจ คลาส หรือเมธอด) ที่มีคำอธิบายประกอบนั้นจำกัดไว้
ดังนี้
คลาสย่อย
ใช้รูปแบบคำอธิบายประกอบ @RestrictTo(RestrictTo.Scope.SUBCLASSES) เพื่อจำกัด
การเข้าถึง API ไว้เฉพาะคลาสย่อย
เฉพาะคลาสที่ขยายคลาสที่มีคำอธิบายประกอบเท่านั้นที่จะเข้าถึง API นี้ได้ ตัวแก้ไขของ Java
protected ไม่ได้จำกัดมากพอ เนื่องจากอนุญาตให้เข้าถึง
จากคลาสที่ไม่เกี่ยวข้องภายในแพ็กเกจเดียวกัน นอกจากนี้ ยังมีกรณีที่คุณต้องการปล่อยเมธอดเป็น
public เพื่อความยืดหยุ่นในอนาคต เนื่องจากคุณไม่สามารถทำให้เมธอดที่เคยเป็น
protected และลบล้างเป็น public ได้ แต่คุณต้องการให้คำแนะนำว่าคลาสนี้มีไว้สำหรับใช้ภายในคลาสหรือจากคลาสย่อยเท่านั้น
ไลบรารี
ใช้รูปแบบคำอธิบายประกอบ @RestrictTo(RestrictTo.Scope.LIBRARY_GROUP_PREFIX) เพื่อ
จำกัดการเข้าถึง API ไว้เฉพาะไลบรารีของคุณ
เฉพาะโค้ดไลบรารีของคุณเท่านั้นที่จะเข้าถึง API ที่มีคำอธิบายประกอบได้ ซึ่งช่วยให้คุณไม่เพียงแต่จัดระเบียบโค้ด
ในลำดับชั้นของแพ็กเกจที่ต้องการเท่านั้น แต่ยังแชร์
โค้ดระหว่างกลุ่มไลบรารีที่เกี่ยวข้องได้ด้วย ตัวเลือกนี้พร้อมใช้งานแล้วสำหรับไลบรารี Jetpack
ที่มีโค้ดการใช้งานจำนวนมากซึ่งไม่ได้มีไว้สำหรับใช้ภายนอก แต่
ต้องเป็น public เพื่อแชร์ในไลบรารี Jetpack เสริมต่างๆ
การทดสอบ
ใช้รูปแบบคำอธิบายประกอบ @RestrictTo(RestrictTo.Scope.TESTS) เพื่อป้องกันไม่ให้นักพัฒนาซอฟต์แวร์คนอื่นๆ เข้าถึง API การทดสอบของคุณ
เฉพาะโค้ดการทดสอบเท่านั้นที่จะเข้าถึง API ที่มีคำอธิบายประกอบได้ ซึ่งจะป้องกันไม่ให้นักพัฒนาซอฟต์แวร์คนอื่นๆ ใช้ API สำหรับการพัฒนาที่คุณตั้งใจไว้เพื่อวัตถุประสงค์ในการทดสอบเท่านั้น