ปรับปรุงการตรวจสอบโค้ดด้วยหมายเหตุ

การใช้เครื่องมือตรวจสอบโค้ด เช่น Lint จะช่วยคุณค้นหาปัญหาและปรับปรุงโค้ดได้ แต่เครื่องมือตรวจสอบจะอนุมานได้เพียงเท่านี้ ตัวอย่างเช่น รหัสทรัพยากร Android ใช้ int เพื่อระบุสตริง กราฟิก สี และทรัพยากรประเภทอื่นๆ เครื่องมือตรวจสอบจึงไม่สามารถบอกได้ว่าคุณระบุทรัพยากรสตริงในตำแหน่งที่ควรระบุสี สถานการณ์นี้หมายความว่าแอปอาจแสดงผลอย่างไม่ถูกต้องหรือไม่ทำงานเลย แม้ว่าคุณจะใช้การตรวจสอบโค้ดก็ตาม

คําอธิบายประกอบช่วยให้คุณระบุคำแนะนำแก่เครื่องมือตรวจสอบโค้ด เช่น Lint เพื่อช่วยตรวจหาปัญหาโค้ดที่ละเอียดยิ่งขึ้น ระบบจะเพิ่มคำอธิบายประกอบเป็นแท็กข้อมูลเมตาที่คุณแนบกับตัวแปร พารามิเตอร์ และค่าที่แสดงผลเพื่อตรวจสอบค่าที่แสดงผลของเมธอด พารามิเตอร์ที่ส่ง ตัวแปรภายใน และช่อง เมื่อใช้ร่วมกับเครื่องมือตรวจสอบโค้ด คําอธิบายประกอบจะช่วยคุณตรวจหาปัญหาต่างๆ เช่น ข้อยกเว้นเกี่ยวกับ Null Pointer และการทับซ้อนกันของประเภททรัพยากร

Android รองรับคำอธิบายประกอบที่หลากหลายผ่านคลังคำอธิบายประกอบของ Jetpack คุณสามารถเข้าถึงคลังผ่านแพ็กเกจ androidx.annotation ได้

หมายเหตุ: หากโมดูลมีการพึ่งพาเครื่องประมวลผลคําอธิบายประกอบ คุณต้องใช้สํารวจการพึ่งพา kapt หรือ ksp สําหรับ Kotlin หรือสํารวจการพึ่งพา annotationProcessor สําหรับ Java เพื่อเพิ่มการพึ่งพานั้น

เพิ่มคำอธิบายประกอบลงในโปรเจ็กต์

หากต้องการเปิดใช้คำอธิบายประกอบในโปรเจ็กต์ ให้เพิ่มandroidx.annotation:annotationข้อกําหนดในไลบรารีหรือแอป ระบบจะตรวจสอบคำอธิบายประกอบที่คุณเพิ่มเมื่อเรียกใช้การตรวจสอบโค้ดหรืองาน lint

เพิ่มการพึ่งพาไลบรารีคำอธิบายประกอบของ Jetpack

คลังคำอธิบายประกอบของ Jetpack เผยแพร่อยู่ในที่เก็บ Maven ของ Google หากต้องการเพิ่มคลังการกำกับเนื้อหาของ Jetpack ลงในโปรเจ็กต์ ให้ใส่บรรทัดต่อไปนี้ในบล็อก 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 เพื่อตรวจสอบว่าตัวแปร พารามิเตอร์ หรือค่าที่แสดงผลเป็นค่าว่างหรือไม่ คําอธิบายประกอบ @Nullable ระบุตัวแปร พารามิเตอร์ หรือค่าที่แสดงผลซึ่งอาจเป็นค่าว่างได้ @NonNull ระบุตัวแปร พารามิเตอร์ หรือค่าที่แสดงผลซึ่งต้องไม่มีค่า Null

เช่น หากมีการส่งตัวแปรภายในซึ่งมีค่า Null เป็นพารามิเตอร์ไปยังเมธอดที่มีคำอธิบายประกอบ @NonNull แนบอยู่กับพารามิเตอร์นั้น การสร้างโค้ดจะสร้างคำเตือนที่ระบุว่ามีความขัดแย้งที่ไม่ใช่ Null นอกจากนี้ การพยายามอ้างอิงผลลัพธ์ของเมธอดที่มีเครื่องหมาย @Nullable โดยไม่ตรวจสอบก่อนว่าผลลัพธ์เป็น Null หรือไม่ จะทำให้เกิดคำเตือนเกี่ยวกับค่า Null ใช้ @Nullable กับผลลัพธ์ของเมธอดก็ต่อเมื่อการใช้เมธอดทุกครั้งต้องตรวจสอบค่าว่างอย่างชัดแจ้ง

ตัวอย่างต่อไปนี้แสดงการใช้งาน Nullability โค้ดตัวอย่าง 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 เพื่ออนุมานและแทรกคําอธิบายประกอบเกี่ยวกับ Nullness ในโค้ดโดยอัตโนมัติ การวิเคราะห์ความสามารถในการเป็น Null จะสแกนสัญญาตลอดลําดับชั้นเมธอดในโค้ดเพื่อตรวจหาสิ่งต่อไปนี้

  • การเรียกใช้เมธอดที่อาจแสดงผลเป็นค่า Null
  • เมธอดที่ไม่ควรแสดงผลลัพธ์เป็นค่าว่าง
  • ตัวแปร เช่น ฟิลด์ ตัวแปรในเครื่อง พารามิเตอร์ ที่สามารถเป็นค่าว่าง
  • ตัวแปร เช่น ฟิลด์ ตัวแปรภายใน ที่พารามิเตอร์ใช้ไม่ได้

จากนั้นการวิเคราะห์จะแทรกคำอธิบายประกอบ Null ที่เหมาะสมโดยอัตโนมัติในตำแหน่งที่ตรวจพบ

หากต้องการเรียกใช้การวิเคราะห์ความสามารถในการเป็น Null ใน Android Studio ให้เลือกวิเคราะห์ > อนุมาน Nullity Android Studio จะแทรกคำอธิบายประกอบ @Nullable และ @NonNull ของ Android ในตำแหน่งที่ตรวจพบในโค้ด หลังจากทําการวิเคราะห์ Null แล้ว แนวทางปฏิบัติที่ดีคือยืนยันคำอธิบายประกอบที่แทรก

หมายเหตุ: เมื่อเพิ่มการกำกับเนื้อหาเกี่ยวกับค่า Null ระบบอาจแนะนำการกำกับเนื้อหา @Nullable และ @NotNull ของ IntelliJ แทนการกำกับเนื้อหาเกี่ยวกับค่า Null ของ Android และอาจนำเข้าไลบรารีที่เกี่ยวข้องโดยอัตโนมัติ อย่างไรก็ตาม เครื่องมือตรวจสอบ Lint ของ 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 จะแตกต่างจากชุดข้อความหลัก ในกรณีของแอประบบที่มีหลายมุมมองในชุดข้อความที่แตกต่างกัน ดังนั้น คุณควรกำกับเนื้อหาวิธีการที่เชื่อมโยงกับลําดับชั้นมุมมองของแอปด้วย @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 ต้องมีค่าประเภท 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 เพื่อตรวจสอบว่าผลลัพธ์หรือค่าที่แสดงผลของเมธอดมีการใช้งานจริง แทนที่จะกำกับเนื้อหาทุกเมธอดที่ไม่ใช่ 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 เพื่อตรวจสอบว่าเมธอดที่ลบล้างเรียกใช้การใช้งานเมธอดของ super

ตัวอย่างต่อไปนี้อธิบายประกอบเมธอด 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 (เช่น |, &, ^ และอื่นๆ) คุณสามารถกําหนดคําอธิบายประกอบด้วยแอตทริบิวต์ 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 {}

...

เมื่อคุณสร้างโค้ดที่มี Flag คำอธิบายประกอบ ระบบจะแสดงคำเตือนหากพารามิเตอร์หรือค่าที่แสดงไม่ได้อ้างอิงรูปแบบที่ถูกต้อง

เก็บคำอธิบายประกอบ

คําอธิบายประกอบ @Keep ช่วยให้มั่นใจว่าระบบจะไม่นําคลาสหรือเมธอดที่มีคําอธิบายประกอบออกเมื่อมีการลดขนาดโค้ดที่เวลาสร้าง โดยปกติแล้วแอตทริบิวต์กำกับนี้จะเพิ่มลงในเมธอดและคลาสที่เข้าถึงผ่านการสะท้อนกลับเพื่อป้องกันไม่ให้คอมไพเลอร์ถือว่าโค้ดไม่ได้ใช้งาน

ข้อควรระวัง: คลาสและเมธอดที่คุณกำกับเนื้อหาโดยใช้ @Keep จะปรากฏใน APK ของแอปเสมอ แม้ว่าคุณจะไม่เคยอ้างอิงคลาสและเมธอดเหล่านี้ในตรรกะของแอปก็ตาม

หากต้องการคงขนาดของแอปให้เล็กอยู่เสมอ ให้พิจารณาว่าจำเป็นต้องเก็บคําอธิบายประกอบแต่ละรายการไว้ในแอปหรือไม่ หากคุณใช้การสะท้อนกลับเพื่อเข้าถึงคลาสหรือเมธอดที่มีคําอธิบายประกอบ ให้ใช้เงื่อนไข -if ในกฎ ProGuard โดยระบุคลาสที่ทําการเรียกใช้การสะท้อนกลับ@Keep

ดูข้อมูลเพิ่มเติมเกี่ยวกับวิธีลดขนาดโค้ดและระบุโค้ดที่จะไม่นำออกได้ที่ลดขนาด สร้างความสับสน และเพิ่มประสิทธิภาพแอป

คําอธิบายประกอบระดับการมองเห็นโค้ด

ใช้คำอธิบายประกอบต่อไปนี้เพื่อระบุระดับการเข้าถึงของโค้ดบางส่วน เช่น เมธอด คลาส ฟิลด์ หรือแพ็กเกจ

ทำให้โค้ดแสดงขึ้นสำหรับการทดสอบ

หมายเหตุกำกับ @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 สําหรับการพัฒนาที่คุณตั้งใจไว้สําหรับวัตถุประสงค์การทดสอบเท่านั้น