ค้นหาชุดข้อความที่ไม่ตอบสนอง

เอกสารนี้แสดงวิธีระบุเทรดที่ไม่ตอบสนองในกลุ่ม ANR ดัมพ์ เทรดที่ไม่ตอบสนองจะแตกต่างกันไปตามประเภทของ ANR ดังที่แสดงใน

ประเภท ANR ชุดข้อความที่ไม่ตอบสนอง
การจ่ายอินพุต เทรดหลัก
อินพุตของเอาต์พุตไม่มีหน้าต่างที่โฟกัสอยู่ เทรดหลัก ANR ประเภทนี้มักไม่ได้เกิดจากการ ชุดข้อความ
Broadcast Receiver (ซิงโครนัส) ชุดข้อความกำลังทำงาน onReceive() นี่คือเทรดหลัก เว้นแต่ว่าตัวแฮนเดิลที่กำหนดเองในเทรดที่ไม่ใช่หลัก ระบุโดยใช้ Context.registerReceiver
Broadcast Receiver (อะซิงโครนัส) ตรวจสอบโค้ดเพื่อดูว่าเทรดหรือ Thread Pool ใดรับผิดชอบ ดำเนินการเพื่อประมวลผลการออกอากาศหลังจาก goAsync จะถูกเรียก
หมดเวลาเรียกใช้บริการ เทรดหลัก
เริ่มบริการที่ทำงานอยู่เบื้องหน้า เทรดหลัก
ผู้ให้บริการเนื้อหาไม่ตอบสนอง ให้ทำอย่างใดอย่างหนึ่งต่อไปนี้
  • เทรด Binder หาก ANR เกิดจากผู้ให้บริการเนื้อหาที่ช้า คำถาม
  • เทรดหลักหาก ANR เกิดจากการเริ่มต้นแอปเป็นเวลานาน
ไม่มีการตอบกลับ onStartJob หรือ วันที่ onStopJob เทรดหลัก

บางครั้งชุดข้อความไม่ตอบสนองเนื่องจากมีสาเหตุหลักของชุดข้อความอื่น หรือกระบวนการ ชุดข้อความไม่ตอบสนองได้เนื่องจากกำลังรอสิ่งต่อไปนี้

  • ล็อกที่เทรดอื่นใช้งานอยู่
  • การเรียกใช้ Binder ที่ช้าไปยังกระบวนการอื่น

สาเหตุที่พบบ่อยของชุดข้อความไม่ตอบสนอง

ต่อไปนี้คือสาเหตุที่พบบ่อยของชุดข้อความไม่ตอบสนอง

การเรียกใช้ Binder ที่ช้า

แม้ว่าการเรียกใช้ Binder ส่วนใหญ่จะรวดเร็ว แต่แท็กยาวๆ ก็อาจจะช้ามาก นี่คือ มีโอกาสสูงที่จะเกิดขึ้นเมื่ออุปกรณ์โหลด หรือชุดข้อความการตอบกลับของ Binder ช้า เช่น จากการช่วงชิงล็อก มีสายเรียกเข้าจำนวนมาก หรือฮาร์ดแวร์ Abstraction Layer (HAL) หมดเวลา

คุณแก้ไขปัญหานี้ได้โดยย้ายการเรียกใช้ Binder แบบซิงโครนัสไปยังเทรดในเบื้องหลัง หากเป็นไปได้ หากต้องมีการเรียกในเทรดหลัก ลองหาสาเหตุ การโทรช้า วิธีที่ดีที่สุดคือการติดตามจาก Perfetto

มองหา BinderProxy.transactNative หรือ Binderproxy.transact ในกลุ่ม ซึ่งหมายความว่ามีการเรียก Binder หลังจากสองบรรทัดนี้ คุณจะเห็น Binder API ที่เรียกใช้ ในตัวอย่างต่อไปนี้ การโทรคือ IAccessibilityManager.addClient

main tid=123

...
android.os.BinderProxy.transactNative (Native method)
android.os.BinderProxy.transact (BinderProxy.java:568)
android.view.accessibility.IAccessibilityManager$Stub$Proxy.addClient (IAccessibilityManager.java:599)
...

การเรียกใช้ Binder ติดต่อกันหลายรายการ

การดำเนินการเรียกใช้ Binder ติดต่อกันหลายครั้งในลูปแคบๆ จะบล็อกเทรดได้ เป็นเวลานาน

I/O ที่ถูกบล็อก

ไม่บล็อก I/O ในเทรดหลัก นี่คือ Antipattern

การช่วงชิงล็อก

หากเทรดถูกบล็อกเมื่อได้รับการล็อก ก็อาจทำให้เกิด ANR ได้

ตัวอย่างต่อไปนี้แสดงให้เห็นว่าเทรดหลักถูกบล็อกเมื่อพยายามดึงข้อมูล ล็อก:

main (tid=1) Blocked

Waiting for com.example.android.apps.foo.BarCache (0x07d657b7) held by
ptz-rcs-28-EDITOR_REMOTE_VIDEO_DOWNLOAD
[...]
at android.app.ActivityThread.handleStopActivity(ActivityThread.java:5412)
[...]

เทรดที่บล็อกกำลังส่งคำขอ HTTP เพื่อดาวน์โหลดวิดีโอ

ptz-rcs-28-EDITOR_REMOTE_VIDEO_DOWNLOAD (tid=110) Waiting

at jdk.internal.misc.Unsafe.park(Native method:0)
at java.util.concurrent.locks.LockSupport.park(LockSupport.java:211)
at java.util.concurrent.locks.AbstractQueuedSynchronizer.acquire(AbstractQueuedSynchronizer.java:715)
at java.util.concurrent.locks.AbstractQueuedSynchronizer.acquireSharedInterruptibly(AbstractQueuedSynchronizer.java:1047)
at java.util.concurrent.CountDownLatch.await(CountDownLatch.java:230)
at com.example.android.apps.foo.HttpRequest.execute(HttpRequest:136)
at com.example.android.apps.foo$Task$VideoLoadTask.downloadVideoToFile(RequestExecutor:711)
[...]

เฟรมราคาแพง

การแสดงภาพสิ่งต่างๆ มากเกินไปในเฟรมเดียวอาจทําให้เทรดหลัก ไม่ตอบสนองภายในระยะเวลาของเฟรม เช่น

  • กำลังแสดงผลรายการนอกหน้าจอที่ไม่จำเป็นหลายรายการ
  • ใช้อัลกอริทึมที่ไม่มีประสิทธิภาพ เช่น O(n^2) เมื่อแสดงผล UI หลายรายการ จากองค์ประกอบเหล่านี้

ถูกบล็อกโดยคอมโพเนนต์อื่น

หากคอมโพเนนต์อื่น เช่น Broadcast Receiver บล็อกเทรดหลักสำหรับ นานกว่า 5 วินาที อาจทำให้เกิด ANR ของการจ่ายงานอินพุตและข้อขัดข้องร้ายแรง

หลีกเลี่ยงการทํางานหนักๆ ในเทรดหลักในคอมโพเนนต์ของแอป เรียกใช้การออกอากาศ ตัวรับในชุดข้อความอื่นเมื่อเป็นไปได้