หน้านี้อธิบายแนวทางปฏิบัติที่แนะนำสำหรับการสร้างวิดเจ็ตขั้นสูงเพื่อประสบการณ์ของผู้ใช้ที่ดียิ่งขึ้น
การเพิ่มประสิทธิภาพสำหรับการอัปเดตเนื้อหาวิดเจ็ต
การอัปเดตเนื้อหาวิดเจ็ตอาจใช้ทรัพยากรในการประมวลผลสูง เพื่อประหยัดการใช้แบตเตอรี่ ให้เพิ่มประสิทธิภาพประเภท ความถี่ และเวลาในการอัปเดต
ประเภทการอัปเดตวิดเจ็ต
การอัปเดตวิดเจ็ตทำได้ 3 วิธี ได้แก่ การอัปเดตทั้งหมด การอัปเดตบางส่วน และการรีเฟรชข้อมูลในกรณีที่เป็นวิดเจ็ตคอลเล็กชัน แต่ละวิธีมีต้นทุนและผลกระทบด้านการประมวลผลที่แตกต่างกัน
ข้อมูลต่อไปนี้จะอธิบายการอัปเดตแต่ละประเภทและให้ข้อมูลโค้ดสำหรับการอัปเดตแต่ละรายการ
- การอัปเดตแบบเต็ม: เรียกใช้
AppWidgetManager.updateAppWidget(int, android.widget.RemoteViews)เพื่ออัปเดตวิดเจ็ตอย่างเต็มรูปแบบ ซึ่งจะแทนที่RemoteViewsที่ระบุไว้ก่อนหน้านี้ด้วยRemoteViewsใหม่ การอัปเดตนี้ใช้ทรัพยากรในการประมวลผลมากที่สุด
val appWidgetManager = AppWidgetManager.getInstance(context) val remoteViews = RemoteViews(context.packageName, R.layout.widgetlayout).apply { setTextViewText(R.id.textview_widget_layout1, "Updated text1") setTextViewText(R.id.textview_widget_layout2, "Updated text2") } appWidgetManager.updateAppWidget(appWidgetId, remoteViews)
- การอัปเดตบางส่วน: เรียกใช้
AppWidgetManager.partiallyUpdateAppWidgetเพื่ออัปเดตบางส่วนของวิดเจ็ต ซึ่งจะรวมRemoteViewsใหม่เข้ากับRemoteViewsที่ระบุไว้ก่อนหน้านี้ ระบบจะไม่สนใจเมธอดนี้หากวิดเจ็ตไม่ได้รับการอัปเดตแบบเต็มอย่างน้อย 1 ครั้งผ่านupdateAppWidget(int[], RemoteViews)
val appWidgetManager = AppWidgetManager.getInstance(context) val remoteViews = RemoteViews(context.packageName, R.layout.widgetlayout).apply { setTextViewText(R.id.textview_widget_layout, "Updated text") } appWidgetManager.partiallyUpdateAppWidget(appWidgetId, remoteViews)
- การรีเฟรชข้อมูลคอลเล็กชัน: เรียกใช้
AppWidgetManager.notifyAppWidgetViewDataChangedเพื่อทำให้ข้อมูลของมุมมองคอลเล็กชันในวิดเจ็ตใช้งานไม่ได้ ซึ่งจะทริกเกอร์RemoteViewsFactory.onDataSetChangedในระหว่างนี้ ข้อมูลเก่าจะแสดงในวิดเจ็ต คุณสามารถทำงานที่มีค่าใช้จ่ายสูงพร้อมกันได้อย่างปลอดภัยด้วยวิธีนี้
val appWidgetManager = AppWidgetManager.getInstance(context) appWidgetManager.notifyAppWidgetViewDataChanged(appWidgetId, R.id.widget_listview)
คุณเรียกใช้เมธอดเหล่านี้ได้จากทุกที่ในแอป ตราบใดที่แอปมี UID เดียวกันกับคลาส AppWidgetProvider ที่เกี่ยวข้อง
กำหนดความถี่ในการอัปเดตวิดเจ็ต
วิดเจ็ตจะอัปเดตเป็นระยะๆ โดยขึ้นอยู่กับค่าที่ระบุสำหรับแอตทริบิวต์ updatePeriodMillis วิดเจ็ตสามารถอัปเดตเพื่อตอบสนองต่อการโต้ตอบของผู้ใช้ การอัปเดตการออกอากาศ หรือทั้ง 2 อย่าง
อัปเดตเป็นระยะๆ
คุณควบคุมความถี่ของการอัปเดตเป็นระยะได้โดยระบุค่าสำหรับ AppWidgetProviderInfo.updatePeriodMillis ใน XML ของ appwidget-provider การอัปเดตแต่ละครั้งจะทริกเกอร์เมธอด AppWidgetProvider.onUpdate() ซึ่งเป็นตำแหน่งที่คุณสามารถวางโค้ดเพื่ออัปเดตวิดเจ็ตได้ อย่างไรก็ตาม ให้พิจารณาทางเลือกสำหรับการอัปเดต Broadcast Receiver ที่อธิบายไว้ในส่วนต่อไปนี้หากวิดเจ็ตต้องโหลดข้อมูลแบบไม่พร้อมกันหรือใช้เวลาอัปเดตนานกว่า 10 วินาที เนื่องจากหลังจากผ่านไป 10 วินาที ระบบจะถือว่า BroadcastReceiver ไม่ตอบสนอง
updatePeriodMillis ไม่รองรับค่าที่น้อยกว่า 30 นาที แต่หากต้องการปิดใช้การอัปเดตเป็นระยะ ให้ระบุ 0
คุณอนุญาตให้ผู้ใช้ปรับความถี่ของการอัปเดตในการกำหนดค่าได้ ตัวอย่างเช่น ผู้ใช้อาจต้องการให้แถบแสดงราคาหุ้นอัปเดตทุก 15 นาที หรือเพียง 4 ครั้งต่อวัน ในกรณีนี้ ให้ตั้งค่า updatePeriodMillis เป็น 0 และใช้ WorkManager แทน
อัปเดตเพื่อตอบสนองต่อการโต้ตอบของผู้ใช้
วิธีที่แนะนำในการอัปเดตวิดเจ็ตตามการโต้ตอบของผู้ใช้มีดังนี้
จากกิจกรรมของแอป: เรียกใช้
AppWidgetManager.updateAppWidgetโดยตรงเพื่อตอบสนองต่อการโต้ตอบของผู้ใช้ เช่น การแตะของผู้ใช้จากการโต้ตอบระยะไกล เช่น การแจ้งเตือนหรือวิดเจ็ตแอป ให้สร้าง
PendingIntentแล้วอัปเดตวิดเจ็ตจากActivity,BroadcastหรือServiceที่เรียกใช้ คุณเลือกลำดับความสำคัญเองได้ เช่น หากคุณเลือกBroadcastสำหรับPendingIntentคุณสามารถเลือกการออกอากาศในเบื้องหน้าเพื่อให้ความสำคัญกับBroadcastReceiverได้
อัปเดตเพื่อตอบสนองต่อเหตุการณ์การออกอากาศ
ตัวอย่างเหตุการณ์การประกาศที่ต้องอัปเดตวิดเจ็ตคือเมื่อผู้ใช้ถ่ายรูป ในกรณีนี้ คุณต้องการอัปเดตวิดเจ็ตเมื่อตรวจพบรูปภาพใหม่
คุณสามารถกำหนดเวลางานด้วย WorkManager และระบุทริกเกอร์ URI เนื้อหาโดยใช้เมธอด Constraints.Builder.addContentUriTrigger
นอกจากนี้ คุณยังลงทะเบียน BroadcastReceiver สำหรับการออกอากาศได้ด้วย เช่น การฟัง ACTION_LOCALE_CHANGED
อย่างไรก็ตาม เนื่องจากวิธีนี้ใช้ทรัพยากรของอุปกรณ์ โปรดใช้อย่างระมัดระวังและฟังเฉพาะการออกอากาศที่เฉพาะเจาะจงเท่านั้น เมื่อมีการเปิดตัวข้อจำกัดการบรอดแคสต์ใน Android 7.0 (ระดับ API 24) และ Android 8.0 (ระดับ API 26) แอปจะไม่สามารถลงทะเบียนการกระจายข้อมูลแบบไม่เจาะจงปลายทางในไฟล์ Manifest ได้ โดยมีข้อยกเว้นบางประการ
ข้อควรพิจารณาเมื่ออัปเดตวิดเจ็ตจาก BroadcastReceiver
หากวิดเจ็ตได้รับการอัปเดตจาก BroadcastReceiver รวมถึง AppWidgetProvider โปรดคำนึงถึงข้อควรพิจารณาต่อไปนี้เกี่ยวกับระยะเวลาและลำดับความสำคัญของการอัปเดตวิดเจ็ต
ระยะเวลาของการอัปเดต
โดยปกติแล้ว ระบบจะอนุญาตให้ Broadcast Receiver ซึ่งมักจะทำงานในเธรดหลักของแอปทำงานได้นานถึง 10 วินาทีก่อนที่จะพิจารณาว่าไม่ตอบสนองและทริกเกอร์ข้อผิดพลาดแอปพลิเคชันไม่ตอบสนอง (ANR) หากต้องการหลีกเลี่ยงการบล็อกเทรดหลักขณะจัดการการออกอากาศ ให้ใช้เมธอด goAsync หากใช้เวลานานกว่านั้นในการอัปเดตวิดเจ็ต ให้พิจารณากำหนดเวลางานโดยใช้ WorkManager
Caution: Any work you do here blocks further broadcasts until it completes,
so it can slow the receiving of later events.
ดูข้อมูลเพิ่มเติมได้ที่ข้อควรพิจารณาด้านความปลอดภัยและแนวทางปฏิบัติแนะนำ
ลำดับความสำคัญของการอัปเดต
โดยค่าเริ่มต้น การออกอากาศ ซึ่งรวมถึงการออกอากาศที่ทำโดยใช้ AppWidgetProvider.onUpdate จะทำงานเป็นกระบวนการเบื้องหลัง ซึ่งหมายความว่าทรัพยากรระบบที่ทำงานหนักเกินไปอาจทำให้การเรียกใช้ Broadcast Receiver ล่าช้า หากต้องการจัดลำดับความสำคัญของการออกอากาศ ให้กำหนดให้เป็นกระบวนการที่ทำงานอยู่เบื้องหน้า
เช่น เพิ่มแฟล็ก Intent.FLAG_RECEIVER_FOREGROUND ลงใน Intent ที่ส่งไปยัง PendingIntent.getBroadcast เมื่อผู้ใช้แตะส่วนใดส่วนหนึ่งของวิดเจ็ต