เป็นคำถามที่ดีมากต้องใช้เวลาในฐานะโปรแกรมเมอร์ Android เพื่อทำความเข้าใจปัญหาอย่างถ่องแท้ AsyncTask มีสองประเด็นหลักที่เกี่ยวข้อง:
- พวกเขาเชื่อมโยงกับวงจรชีวิตของกิจกรรมไม่ดี
- พวกเขาสร้างการรั่วไหลของหน่วยความจำได้ง่ายมาก
ภายในแอปRoboSpice Motivations ( มีให้บริการบน Google Play ) เราตอบคำถามนั้นโดยละเอียด จะให้มุมมองเชิงลึกของ AsyncTasks, Loaders, คุณสมบัติและข้อเสียและยังแนะนำให้คุณรู้จักกับโซลูชันทางเลือกสำหรับคำขอเครือข่าย: RoboSpice คำขอเครือข่ายเป็นข้อกำหนดทั่วไปใน Android และเป็นไปตามการดำเนินงานที่ยาวนาน นี่คือข้อความที่ตัดตอนมาจากแอพ:
วงจรชีวิตของ AsyncTask และ Activity
AsyncTasks ไม่เป็นไปตามวงจรชีวิตของอินสแตนซ์กิจกรรม หากคุณเริ่ม AsyncTask ภายในกิจกรรมและคุณหมุนอุปกรณ์กิจกรรมนั้นจะถูกทำลายและจะมีการสร้างอินสแตนซ์ใหม่ แต่ AsyncTask จะไม่ตาย มันจะมีชีวิตอยู่ต่อไปจนกว่าจะสำเร็จ
และเมื่อเสร็จสิ้น AsyncTask จะไม่อัปเดต UI ของกิจกรรมใหม่ แน่นอนมันอัปเดตอินสแตนซ์เดิมของกิจกรรมที่ไม่ปรากฏอีกต่อไป สิ่งนี้สามารถนำไปสู่ Exception ของชนิด java.lang.IllegalArgumentException: ดูไม่ได้แนบกับตัวจัดการหน้าต่างถ้าคุณใช้เช่น findViewById เพื่อดึงมุมมองภายในกิจกรรม
ปัญหาหน่วยความจำรั่ว
สะดวกมากในการสร้าง AsyncTasks เป็นคลาสภายในของกิจกรรมของคุณ เนื่องจาก AsyncTask จะต้องปรับเปลี่ยนมุมมองของกิจกรรมเมื่องานเสร็จสมบูรณ์หรืออยู่ระหว่างดำเนินการการใช้คลาสภายในของกิจกรรมจึงดูสะดวก: คลาสภายในสามารถเข้าถึงฟิลด์ใดก็ได้ของคลาสชั้นนอกโดยตรง
อย่างไรก็ตามมันหมายความว่าคลาสภายในจะมีการอ้างอิงที่มองไม่เห็นในอินสแตนซ์คลาสภายนอกนั่นคือกิจกรรม
ในระยะยาวสิ่งนี้ก่อให้เกิดการรั่วไหลของหน่วยความจำ: หาก AsyncTask ใช้งานได้นานจะทำให้กิจกรรม "มีชีวิต" ในขณะที่ Android ต้องการกำจัดมันออกไปเนื่องจากไม่สามารถแสดงได้อีก กิจกรรมนี้ไม่สามารถรวบรวมขยะได้และเป็นกลไกหลักสำหรับ Android ในการรักษาทรัพยากรในอุปกรณ์
เป็นความคิดที่แย่มากที่จะใช้ AsyncTasks สำหรับการทำงานที่ยาวนาน อย่างไรก็ตามเหมาะสำหรับคนที่มีชีวิตสั้น ๆ เช่นการอัปเดตมุมมองหลังจาก 1 หรือ 2 วินาที
ฉันขอแนะนำให้คุณดาวน์โหลดแอป RoboSpice Motivationsซึ่งจะอธิบายในเชิงลึกนี้และให้ตัวอย่างและการสาธิตวิธีต่างๆในการดำเนินการเบื้องหลังบางอย่าง
doInBackground
ฟังก์ชันที่ใช้งานได้ยาวนานจะหยุดหน้าจอหากไม่ได้ใช้แถบความคืบหน้า