Navigation Arch Component สร้างการรั่วไหลของหน่วยความจำบวกที่ผิดพลาดหรือไม่


14

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

ฉันใช้คอมโพเนนต์ arch navigation และทำตามรูปแบบ MVVM ฉันเพิ่มห้องสมุด LeakCanary ในภายหลังในการพัฒนาโครงการและมันก็เริ่มให้คำเตือนเกี่ยวกับอินสแตนซ์ที่เก็บไว้ทันทีเมื่อฉันนำทางระหว่างหน้าจอ

ปัญหาเกิดขึ้นเมื่อฉันเพิ่มแฟรกเมนต์ลงในสแต็กหลัง เมื่อเพิ่มแฟรกเมนต์ที่เพิ่มลงในสแต็กหลังแต่ละตัวนับอินสแตนซ์ที่เก็บไว้จะเพิ่มขึ้น เมื่อถึงค่าขีด จำกัด 5 LeakCanary จะทิ้งฮีปและจัดทำรายงาน

แต่ถ้าฉันคลิกที่ปุ่มย้อนกลับและกลับสู่หน้าจอก่อนหน้าตัวนับอินสแตนซ์ที่เก็บไว้จะลดลงและในที่สุดเมื่อกลับสู่หน้าจอที่ 1 อินสแตนซ์ที่เก็บไว้ทั้งหมดจะหายไป

ถ้าฉันดูรายงานการวิเคราะห์ฮีปมันบอกว่าตัวแปร CoordinatorLayout ซึ่งเป็นการอ้างอิงถึงCoordinatorLayoutin in xml ได้รั่วไหลออกมา หากฉันลบตัวแปรและการใช้งานทั้งหมดแล้วเรียกใช้แอปอีกครั้งฉันเห็นปัญหาเดียวกัน แต่ตอนนี้มีตัวแปรอื่นที่อ้างอิงถึงมุมมองอื่นใน xml ฉันพยายามลบมุมมองทั้งหมดและการใช้งานที่ LeakCanary รายงานว่าเป็นการรั่วไหล เมื่อมันบอกว่า a TextViewซึ่งเพิ่งใช้ในการตั้งค่าข้อความonViewCreatedและไม่ได้ใช้ที่อื่นถูกรั่วฉันเริ่มสงสัยว่ามีปัญหาในรหัสของฉัน

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

ฉันสงสัยว่าองค์ประกอบการนำทางจะรักษาอินสแตนซ์ของชิ้นส่วนเมื่อมันอยู่ในกองหลังและ LeakCanary เห็นว่าเป็นรอยรั่ว

คำตอบ:


24

นั่นคือสิ่งที่ Fragments ใน back stack ทำงาน (และการนำทางใช้แค่ Fragment APIs ที่มีอยู่แล้ว): มุมมองของ Fragment ถูกทำลาย แต่ Fragment เองไม่ถูกทำลาย - มันถูกเก็บไว้ในCREATEDสถานะจนกว่าคุณจะกดปุ่มย้อนกลับและกลับสู่ Fragment (หลังจากนั้นonCreateView()จะถูกเรียกอีกครั้งและคุณจะย้ายกลับไปที่RESUMED)

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

คุณต้องยกเลิกการอ้างอิงของคุณไปยังมุมมองonDestroyViewเนื่องจากเป็นสัญญาณว่าระบบจะไม่ใช้มุมมองอีกต่อไปและสามารถเก็บขยะได้อย่างปลอดภัยหากไม่ใช่เพื่อการอ้างอิงต่อไปยังมุมมอง


2
Android View Binding แก้ปัญหานี้หรือไม่? ฉันไม่พบเอกสารใด ๆ ว่าการอ้างอิงไปยังมุมมองการรวมการดู (อาจเป็นวัตถุการรวมตัวเอง) จะถูก 'โมฆะโดยอัตโนมัติ' onDestroyViewด้วยการดูการผูก
ทิม Malseed

3
@TimMalseed - คุณจำเป็นต้องลบการอ้างอิงของคุณไปยังวัตถุที่มีผลผูกพันด้วยตนเองไม่มีอะไรเกิดขึ้นโดยอัตโนมัติ
ianhanniballake

1
@Emmanuel - คุณต้องปล่อยการอ้างอิงของคุณไปยังวัตถุที่มีผลผูกพันตัวเองตามที่ถือการอ้างอิงอย่างหนักเพื่อการดูมันเป็นเจ้าของ
ianhanniballake

1
@Emmanuel - คุณสามารถส่งคำขอคุณสมบัติได้ตลอดเวลา!
ianhanniballake

1
@ Emanuel - ฉันคิดว่ามันจะเป็นการเปลี่ยนแปลงในพฤติกรรมอย่างแน่นอน (ซึ่งอาจหมายถึงว่ามันเป็นสถานะการเลือกที่แยกต่างหาก) แต่การมี LifecycleOwner ที่ถูกต้องจะมีข้อมูลเพียงพอที่จะแก้ไขปัญหาหน่วยความจำทั้งหมด
ianhanniballake
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.