กระบวนการเบื้องหลังอาจใช้หน่วยความจำและแบตเตอรี่มาก เช่น การกระจายข้อมูลแบบไม่เจาะจงปลายทางอาจเริ่มกระบวนการเบื้องหลังจำนวนมากที่ลงทะเบียนเพื่อรอกิจกรรม แม้ว่ากระบวนการเหล่านั้นอาจไม่ได้ทำงานมากนักก็ตาม ซึ่งอาจส่งผลกระทบอย่างมากต่อประสิทธิภาพของอุปกรณ์และประสบการณ์ของผู้ใช้
โปรดตรวจสอบว่าคุณใช้ API ที่เหมาะสมกับงานเบื้องหลังเพื่อหลีกเลี่ยงข้อจำกัดของระบบ เอกสารประกอบ ภาพรวมของงานเบื้องหลังจะช่วยคุณเลือก API ที่เหมาะสมกับความต้องการ
ข้อจำกัดที่ผู้ใช้เป็นผู้กำหนด
หากแอปแสดงลักษณะการทำงานที่ไม่ดีบางอย่างที่อธิบายไว้ใน Android vitals, ระบบจะแจ้งให้ผู้ใช้จำกัดการเข้าถึงทรัพยากรระบบของแอปนั้น
หากระบบสังเกตเห็นว่าแอปใช้ทรัพยากรมากเกินไป ระบบจะแจ้งให้ผู้ใช้ทราบและให้ตัวเลือกแก่ผู้ใช้ในการจำกัดการดำเนินการของแอป ลักษณะการทำงานที่อาจเรียกให้การแจ้งเตือนแสดงขึ้นมีดังนี้
- Wake Lock มากเกินไป: Wake Lock บางส่วน 1 รายการที่ทำงานเป็นเวลา 1 ชั่วโมงเมื่อหน้าจอ ปิดอยู่
- บริการเบื้องหลังมากเกินไป: หากแอปกำหนดเป้าหมายเป็น API ระดับต่ำกว่า 26 และมีบริการเบื้องหลังมากเกินไป
ข้อจำกัดที่กำหนดขึ้นอย่างแม่นยำจะขึ้นอยู่กับผู้ผลิตอุปกรณ์ เช่น ในบิลด์ AOSP แอปที่ถูกจำกัดจะไม่สามารถเรียกใช้งาน สร้างการปลุก หรือใช้เครือข่ายได้ ยกเว้นเมื่อแอปอยู่ในเบื้องหน้า
ข้อจำกัดในการรับการออกอากาศกิจกรรมเครือข่าย
แอปจะไม่ได้รับการออกอากาศ CONNECTIVITY_ACTION หากลงทะเบียนเพื่อ
รับการออกอากาศดังกล่าวในไฟล์ Manifest และกระบวนการที่ขึ้นอยู่กับการออกอากาศนี้
จะไม่เริ่มทำงาน ซึ่งอาจก่อให้เกิดปัญหาสำหรับแอปที่ต้องการรอกิจกรรมสำหรับการเปลี่ยนแปลงเครือข่ายหรือดำเนินการกิจกรรมเครือข่ายจำนวนมากเมื่ออุปกรณ์เชื่อมต่อกับเครือข่ายที่ไม่มีการวัดปริมาณอินเทอร์เน็ต เฟรมเวิร์ก Android มีโซลูชันหลายอย่างเพื่อหลีกเลี่ยงข้อจำกัดนี้ แต่การเลือกโซลูชันที่เหมาะสมจะขึ้นอยู่กับสิ่งที่คุณต้องการให้แอปทำ
กำหนดเวลาให้ทำงานเมื่อมีการเชื่อมต่อที่ไม่มีการวัดปริมาณอินเทอร์เน็ต
เมื่อสร้าง WorkRequest ให้เพิ่ม Constraint ของ NetworkType.UNMETERED
fun scheduleWork(context: Context) {
val workManager = WorkManager.getInstance(context)
val workRequest = OneTimeWorkRequestBuilder<MyWorker>()
.setConstraints(
Constraints.Builder()
.setRequiredNetworkType(NetworkType.UNMETERED)
.build()
)
.build()
workManager.enqueue(workRequest)
}
เมื่อตรงตามเงื่อนไขของงาน แอปจะได้รับการเรียกกลับเพื่อเรียกใช้
เมธอด doWork() ในคลาส Worker ที่ระบุ
ตรวจสอบการเชื่อมต่อเครือข่ายขณะที่แอปกำลังทำงาน
แอปที่กำลังทำงานจะยังคงรับฟัง CONNECTIVITY_CHANGE ได้ด้วย
BroadcastReceiver ที่ลงทะเบียนไว้ อย่างไรก็ตาม API ของ ConnectivityManager
มีวิธีที่เชื่อถือได้มากกว่าในการขอการเรียกกลับเมื่อตรงตามเงื่อนไขเครือข่ายที่ระบุเท่านั้น
NetworkRequest ออบเจ็กต์จะกำหนดพารามิเตอร์ของการเรียกกลับเครือข่ายใน
แง่ของ NetworkCapabilities คุณสร้างออบเจ็กต์ NetworkRequest ด้วยคลาส NetworkRequest.Builder registerNetworkCallback
จากนั้นจะส่งออบเจ็กต์ NetworkRequest ไปยังระบบ เมื่อตรงตามเงื่อนไขเครือข่าย แอปจะได้รับการเรียกกลับเพื่อเรียกใช้เมธอด
onAvailable() ที่กำหนดไว้ในคลาส
ConnectivityManager.NetworkCallback
แอปจะยังคงได้รับการเรียกกลับจนกว่าแอปจะออกหรือเรียกใช้ unregisterNetworkCallback()
ข้อจำกัดในการรับการออกอากาศรูปภาพและวิดีโอ
แอปจะไม่สามารถส่งหรือรับการออกอากาศ ACTION_NEW_PICTURE หรือ ACTION_NEW_VIDEO ได้ ข้อจำกัดนี้ช่วยลดผลกระทบต่อประสิทธิภาพและประสบการณ์ของผู้ใช้เมื่อแอปหลายแอปต้องทำงานเพื่อประมวลผลรูปภาพหรือวิดีโอใหม่
ระบุผู้ออกเนื้อหาที่ทริกเกอร์งาน
WorkerParameters ช่วยให้แอปได้รับข้อมูลที่เป็นประโยชน์เกี่ยวกับผู้ออกเนื้อหาและ URI ที่ทริกเกอร์งาน ดังนี้
List<Uri> getTriggeredContentUris()
แสดงรายการ URI ที่ทริกเกอร์งาน รายการนี้จะว่างเปล่าในกรณีที่ไม่มี URI ใดทริกเกอร์งาน (เช่น งานถูกทริกเกอร์เนื่องจากกำหนดเวลาหรือเหตุผลอื่นๆ) หรือจำนวน URI ที่เปลี่ยนแปลงมีมากกว่า 50 รายการ
List<String> getTriggeredContentAuthorities()
แสดงรายการสตริงของผู้ออกเนื้อหาที่ทริกเกอร์งาน หากรายการที่แสดงไม่ว่างเปล่า ให้ใช้ getTriggeredContentUris() เพื่อดึงรายละเอียดของ URI ที่เปลี่ยนแปลง
โค้ดตัวอย่างต่อไปนี้จะลบล้างเมธอด CoroutineWorker.doWork()
และบันทึกผู้ออกเนื้อหาและ URI ที่ทริกเกอร์งาน
class MyWorker(
appContext: Context,
params: WorkerParameters
): CoroutineWorker(appContext, params)
override suspend fun doWork(): Result {
StringBuilder().apply {
append("Media content has changed:\n")
params.triggeredContentAuthorities
.takeIf { it.isNotEmpty() }
?.let { authorities ->
append("Authorities: ${authorities.joinToString(", ")}\n")
append(params.triggeredContentUris.joinToString("\n"))
} ?: append("(No content)")
Log.i(TAG, toString())
}
return Result.success()
}
}
ทดสอบแอปภายใต้ข้อจำกัดของระบบ
การเพิ่มประสิทธิภาพแอปให้ทำงานในอุปกรณ์ที่มีหน่วยความจำเหลือน้อยหรือในสภาวะที่มีหน่วยความจำเหลือน้อยจะช่วยปรับปรุงประสิทธิภาพและประสบการณ์ของผู้ใช้ การนำการขึ้นอยู่กับบริการเบื้องหลังและ BroadcastReceiver โดยนัยที่ลงทะเบียนไว้ในไฟล์ Manifest ออกจะช่วยให้แอปทำงานได้ดีขึ้นในอุปกรณ์ดังกล่าว เราขอแนะนำให้คุณเพิ่มประสิทธิภาพแอปให้ทำงานได้โดยไม่ต้องใช้กระบวนการเบื้องหลังเหล่านี้เลย
คำสั่ง Android Debug Bridge (ADB) เพิ่มเติมบางคำสั่งจะช่วยคุณทดสอบลักษณะการทำงานของแอป เมื่อปิดใช้กระบวนการเบื้องหลังเหล่านั้น
หากต้องการจำลองสภาวะที่ไม่มีการออกอากาศโดยนัยและบริการเบื้องหลัง ให้ป้อนคำสั่งต่อไปนี้
$ adb shell cmd appops set <package_name> RUN_IN_BACKGROUND ignoreหากต้องการเปิดใช้การออกอากาศโดยนัยและบริการเบื้องหลังอีกครั้ง ให้ป้อนคำสั่งต่อไปนี้
$ adb shell cmd appops set <package_name> RUN_IN_BACKGROUND allow
เพิ่มประสิทธิภาพแอปเพิ่มเติม
ดูวิธีอื่นๆ ที่ดีในการเพิ่มประสิทธิภาพลักษณะการทำงานของงานเบื้องหลังได้ใน เอกสารประกอบเพิ่มประสิทธิภาพการใช้แบตเตอรี่สำหรับ API การกำหนดเวลาของงาน