ทำให้แอปปรับเปลี่ยนตามอุปกรณ์อยู่เสมอ

รูปที่ 1 กล่องโต้ตอบ ANR ที่แสดงต่อผู้ใช้

เอกสารนี้อธิบายวิธีที่ระบบ Android พิจารณาว่าแอปไม่ตอบสนองหรือไม่ และแสดงวิธีทำให้แอปตอบสนองอยู่เสมอ

ไม่ว่าโค้ดของคุณจะเขียนได้ดีเพียงใด แอปก็อาจยังคง ทำงานช้า ค้าง หยุดทำงานเป็นเวลานาน หรือใช้เวลานานเกินไปในการประมวลผล อินพุต หากแอปของคุณอยู่เบื้องหน้าและไม่ตอบสนอง ผู้ใช้จะได้รับกล่องโต้ตอบ แอปพลิเคชันไม่ตอบสนอง (ANR) ดังที่แสดงในรูปที่ 1 กล่องโต้ตอบ ANR ช่วยให้ผู้ใช้บังคับปิดแอปได้ หากแอปไม่ได้อยู่ในเบื้องหน้า ระบบจะ หยุดแอปโดยไม่มีการแจ้งเตือน การออกแบบการตอบสนองในแอปเป็นสิ่งสำคัญที่จะช่วย ลดกล่องโต้ตอบ ANR

ทริกเกอร์ ANR

โดยปกติแล้ว ระบบจะแสดง ANR หากแอปตอบสนองต่อข้อมูลจากผู้ใช้ใน เธรดหลักไม่ได้ ซึ่งเรียกอีกอย่างว่าเธรด UI ทำให้ระบบ ประมวลผลเหตุการณ์อินพุตจากผู้ใช้ที่เข้ามาไม่ได้

ตัวอย่างเช่น ANR อาจเกิดขึ้นหากแอปดำเนินการ I/O ที่บล็อก เช่น การเข้าถึงเครือข่าย ใน UI เธรด อีกตัวอย่างหนึ่งคือเมื่อแอปใช้เวลามากเกินไปในการสร้างโครงสร้างในหน่วยความจำที่ซับซ้อนหรือคำนวณการเคลื่อนไหวถัดไปในเกมบนเทรด UI

ใน Android ActivityManager และบริการของระบบ WindowManager จะตรวจสอบการตอบสนองของแอป Android จะแสดงกล่องโต้ตอบ ANR สำหรับแอป เมื่อตรวจพบเงื่อนไขอย่างใดอย่างหนึ่งต่อไปนี้

  • ไม่มีการตอบสนองต่อเหตุการณ์อินพุต เช่น เหตุการณ์การกดแป้นหรือการแตะหน้าจอ ภายใน 5 วินาที
  • BroadcastReceiver ไม่ได้ ดำเนินการให้เสร็จภายใน 10-20 วินาทีสำหรับ Intent ที่ทำงานในเบื้องหน้า ดูข้อมูลเพิ่มเติมได้ที่การหมดเวลาของ Broadcast Receiver

หลีกเลี่ยง ANR

เคล็ดลับทั่วไปในการหลีกเลี่ยง ANR มีดังนี้ ดูรายละเอียดเพิ่มเติมเกี่ยวกับการวินิจฉัย และการแก้ไขข้อบกพร่องของ ANR ประเภทต่างๆ ได้ในหน้าอื่นๆ ในส่วนนี้

  • อย่าบล็อกเทรดหลักตลอดเวลา และใช้เทรดอย่างมีกลยุทธ์

    • อย่าดำเนินการที่บล็อกหรือดำเนินการที่ใช้เวลานานในเทรดหลักของแอป แต่ให้สร้างเธรดของ Worker แล้วทำงานส่วนใหญ่ในเธรดนั้นแทน

    • พยายามลดการแย่งล็อกระหว่างเทรดหลักกับเทรดอื่นๆ

    • ลดงานที่ไม่เกี่ยวข้องกับ UI ในเทรดหลัก เช่น เมื่อจัดการการออกอากาศหรือเรียกใช้บริการ เมธอดที่ทำงานในเทรด UI ต้อง ทำงานในเทรดนั้นให้น้อยที่สุด โดยเฉพาะอย่างยิ่ง กิจกรรมต้อง ทําให้น้อยที่สุดเท่าที่จะเป็นไปได้ในการตั้งค่าในเมธอดวงจรที่สําคัญ เช่น onCreate() และ onResume() ดูข้อมูลเพิ่มเติมเกี่ยวกับโซลูชันที่มีให้สำหรับการกำหนดเวลาการทำงานในเธรดเบื้องหลังและการสื่อสารกลับไปยัง UI ได้ที่ภาพรวมการทำงานเบื้องหลัง

    • โปรดระมัดระวังเมื่อแชร์ Thread Pool ระหว่างคอมโพเนนต์ อย่าใช้เธรดเดียวกันสำหรับ การดำเนินการที่อาจบล็อกเป็นเวลานานและงานที่ต้องดำเนินการอย่างรวดเร็ว เช่น การรับการออกอากาศ

  • รักษาความเร็วในการเริ่มต้นแอป ลดการดำเนินการที่ช้าหรือมีการบล็อกในโค้ดเริ่มต้นของแอป เช่น เมธอดที่เรียกใช้ระหว่างการเริ่มต้น Dagger

  • หากคุณใช้ BroadcastReceiver ให้พิจารณาเรียกใช้ BroadcastReceiver ใน เธรดที่ไม่ใช่เธรดหลักโดยใช้ Context.registerReceiver ดูข้อมูลเพิ่มเติมได้ที่ANR ใน BroadcastReceiver

    • หากใช้ goAsync() โปรดตรวจสอบว่ามีการเรียกใช้ PendingResult.finish อย่างรวดเร็วก่อนที่ ANR จะหมดเวลา

ANR ใน BroadcastReceiver

BroadcastReceiverเวลาในการดำเนินการถูกจำกัดเนื่องจากตัวรับสัญญาณการออกอากาศ มีไว้เพื่อทำงานเล็กๆ น้อยๆ แบบไม่ต่อเนื่องในเบื้องหลัง เช่น การบันทึกการตั้งค่าหรือการลงทะเบียน Notification ดังนั้น เช่นเดียวกับเมธอดอื่นๆ ที่เรียกใช้ใน UI เธรด แอปต้องหลีกเลี่ยงการดำเนินการหรือการคำนวณที่อาจใช้เวลานานใน BroadcastReceiver แทนที่จะทำงานที่ใช้เวลานานผ่านเทรด UI ให้ทำงานเหล่านั้นในเบื้องหลังเพื่อดำเนินการในภายหลัง ดูข้อมูลเพิ่มเติมเกี่ยวกับวิธีแก้ปัญหาที่เป็นไปได้ในภาพรวมของงานในเบื้องหลัง

ปัญหาที่พบได้ทั่วไปอีกอย่างหนึ่งเกี่ยวกับออบเจ็กต์ BroadcastReceiver เกิดขึ้นเมื่อมีการเรียกใช้บ่อยเกินไป การดำเนินการเบื้องหลังบ่อยๆ อาจลดปริมาณหน่วยความจำ ที่แอปอื่นๆ ใช้งานได้ ดูข้อมูลเพิ่มเติมเกี่ยวกับวิธีเปิดและปิดใช้ BroadcastReceiver ออบเจ็กต์อย่างมีประสิทธิภาพได้ที่ภาพรวมการออกอากาศ

เสริมสร้างการตอบสนอง

โดยทั่วไปแล้ว 100-200 มิลลิวินาทีคือเกณฑ์ที่ผู้ใช้จะรู้สึกว่าแอปช้า เคล็ดลับเพิ่มเติมในการทำให้แอปดูตอบสนองต่อผู้ใช้มีดังนี้

  • หากแอปทำงานในเบื้องหลังเพื่อตอบสนองต่อข้อมูลที่ผู้ใช้ป้อน ให้แสดงความคืบหน้า เช่น ใช้ ProgressBar ใน UI

  • สำหรับเกมโดยเฉพาะ ให้คำนวณการเคลื่อนไหวใน Worker Thread

  • หากแอปมีระยะการตั้งค่าเริ่มต้นที่ใช้เวลานาน ให้ลองแสดงหน้าจอแนะนำหรือแสดงผลมุมมองหลักให้เร็วที่สุด ระบุว่ากำลังโหลดและกรอกข้อมูลแบบไม่พร้อมกัน ไม่ว่าในกรณีใด เราขอแนะนำให้ระบุว่ามีการดำเนินการอยู่ เพื่อให้ผู้ใช้ไม่เข้าใจว่าแอปค้าง

  • ใช้เครื่องมือประสิทธิภาพ เช่น Perfetto และ CPU Profiler เพื่อ ระบุคอขวดในการตอบสนองของแอป