ฉันได้ตรวจสอบปัญหานี้มาหลายเดือนแล้วและหาวิธีแก้ปัญหาที่แตกต่างกันไปซึ่งฉันไม่พอใจเพราะมันเป็นแฮ็คขนาดใหญ่ ฉันยังไม่สามารถเชื่อได้ว่าคลาสที่มีข้อบกพร่องด้านการออกแบบทำให้มันเข้ากับกรอบงานและไม่มีใครพูดถึงมันดังนั้นฉันคิดว่าฉันต้องพลาดบางสิ่งบางอย่าง
AsyncTask
ปัญหาอยู่ที่ ตามเอกสารนั้น
"อนุญาตให้ดำเนินการพื้นหลังและเผยแพร่ผลลัพธ์บนเธรด UI โดยไม่ต้องจัดการกับเธรดและ / หรือตัวจัดการ"
ตัวอย่างแล้วยังแสดงให้เห็นว่าบางอย่างที่เป็นแบบอย่างวิธีการที่เรียกว่าshowDialog()
onPostExecute()
นี้ แต่ดูเหมือนว่าที่วางแผนอย่างสิ้นเชิงกับผมเพราะแสดงโต้ตอบเสมอต้องมีการอ้างอิงถึงที่ถูกต้องContext
และ AsyncTask ไม่ต้องถืออ้างอิงที่แข็งแกร่งให้กับวัตถุบริบท
เหตุผลชัดเจน: เกิดอะไรขึ้นถ้ากิจกรรมถูกทำลายซึ่งก่อให้เกิดงาน? สิ่งนี้สามารถเกิดขึ้นได้ตลอดเวลาเช่นเนื่องจากคุณพลิกหน้าจอ หากงานนั้นจะมีการอ้างอิงถึงบริบทที่สร้างคุณไม่เพียง แต่จะถือวัตถุบริบทที่ไร้ประโยชน์ (หน้าต่างจะถูกทำลายและการโต้ตอบ UI ใด ๆจะล้มเหลวด้วยข้อยกเว้น!) คุณยังมีความเสี่ยงในการสร้าง หน่วยความจำรั่ว
ยกเว้นว่าตรรกะของฉันมีข้อบกพร่องนี่แปลเป็น: onPostExecute()
ไร้ประโยชน์อย่างสิ้นเชิงเพราะวิธีนี้จะทำงานบนเธรด UI ได้ดีเพียงใดหากคุณไม่สามารถเข้าถึงบริบทใด ๆ คุณไม่สามารถทำอะไรที่มีความหมายได้ที่นี่
วิธีแก้ปัญหาหนึ่งคือการไม่ส่งอินสแตนซ์บริบทไปยัง AsyncTask แต่เป็นHandler
อินสแตนซ์ ใช้งานได้: เนื่องจากตัวจัดการผูกบริบทและภารกิจไว้อย่างหลวม ๆ คุณสามารถแลกเปลี่ยนข้อความระหว่างกันโดยไม่เสี่ยงต่อการรั่วไหล (ใช่ไหม) แต่นั่นหมายความว่าสถานที่ตั้งของ AsyncTask คือคุณไม่จำเป็นต้องกังวลกับตัวจัดการผิด ดูเหมือนว่าการใช้ Handler ในทางที่ผิดเนื่องจากคุณกำลังส่งและรับข้อความในเธรดเดียวกัน (คุณสร้างมันบนเธรด UI และส่งผ่านมันใน onPostExecute () ซึ่งยังทำงานบนเธรด UI)
ยิ่งไปกว่านั้นคุณยังมีปัญหาว่าเมื่อบริบทถูกทำลายคุณไม่มีบันทึกของงานที่ถูกไล่ออก นั่นหมายความว่าคุณต้องเริ่มงานใหม่เมื่อสร้างบริบทขึ้นมาใหม่เช่นหลังจากการเปลี่ยนแนวหน้าจอ ช้าและสิ้นเปลือง
วิธีแก้ปัญหาของฉันในเรื่องนี้ (ตามที่นำไปใช้ในไลบรารี Droid-Fu ) คือการรักษาการแมปของWeakReference
ชื่อคอมโพเนนต์ไปยังอินสแตนซ์ปัจจุบันของพวกเขาบนวัตถุแอปพลิเคชันที่ไม่ซ้ำกัน เมื่อใดก็ตามที่ AsyncTask เริ่มต้นมันจะบันทึกบริบทการโทรในแผนที่นั้นและในทุกการติดต่อกลับมันจะดึงอินสแตนซ์บริบทปัจจุบันจากการทำแผนที่นั้น สิ่งนี้ทำให้มั่นใจได้ว่าคุณจะไม่อ้างอิงอินสแตนซ์บริบทเก่าและคุณสามารถเข้าถึงบริบทที่ถูกต้องในการเรียกกลับเพื่อให้คุณสามารถใช้ UI ที่มีความหมายได้ นอกจากนี้ยังไม่รั่วไหลเนื่องจากการอ้างอิงอ่อนแอและถูกล้างเมื่อไม่มีอินสแตนซ์ขององค์ประกอบที่กำหนดอีกต่อไป
ถึงกระนั้นมันก็เป็นวิธีการแก้ปัญหาที่ซับซ้อนและต้องการให้ชั้นย่อยของห้องสมุด Droid-Fu บางคลาสทำให้วิธีการนี้ค่อนข้างน่ารำคาญ
ตอนนี้ฉันแค่อยากรู้ว่า:ฉันเพิ่งทำอะไรบางอย่างหายไปอย่างมากมายหรือว่า AsyncTask มีข้อบกพร่องจริงๆหรือ ประสบการณ์ของคุณทำงานกับมันอย่างไร คุณแก้ปัญหาเหล่านี้ได้อย่างไร
ขอบคุณสำหรับข้อมูลของคุณ