กระบวนการและวงจรชีวิตของแอป

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

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

นักพัฒนาแอปต้องเข้าใจว่าคอมโพเนนต์ต่างๆ ของแอป (โดยเฉพาะ Activity, Service และ BroadcastReceiver) ส่งผลต่ออายุการใช้งานของกระบวนการของแอปอย่างไร การใช้คอมโพเนนต์เหล่านี้อย่างไม่ถูกต้องอาจส่งผลให้ระบบหยุดกระบวนการของแอปพลิเคชันขณะที่ดำเนินการงานสำคัญ

ตัวอย่างที่พบบ่อยของข้อบกพร่องเกี่ยวกับวงจรกระบวนการคือ BroadcastReceiver ที่เริ่มต้นเธรดเมื่อได้รับ Intent ในเมธอด BroadcastReceiver.onReceive() แล้วแสดงผลลัพธ์จากฟังก์ชัน เมื่อกลับมาแล้ว ระบบจะถือว่า BroadcastReceiver ไม่มีการใช้งานอีกต่อไป และไม่จำเป็นต้องใช้กระบวนการโฮสติ้งอีกต่อไป เว้นแต่ว่าคอมโพเนนต์แอปพลิเคชันอื่นๆ จะยังคงใช้งานอยู่

ดังนั้นระบบจึงสามารถฆ่ากระบวนการได้ทุกเมื่อเพื่อเรียกคืนหน่วยความจำ และการดำเนินการดังกล่าวจะสิ้นสุดเธรดที่สร้างขึ้นซึ่งทำงานอยู่ในกระบวนการ โดยปกติแล้ววิธีแก้ปัญหานี้คือการกําหนดเวลาJobServiceจากBroadcastReceiverเพื่อให้ระบบทราบว่ามีงานเกิดขึ้นในกระบวนการ

Android จะจัดลำดับความสำคัญของแต่ละกระบวนการตามคอมโพเนนต์ที่ทำงานอยู่และสถานะของคอมโพเนนต์เหล่านั้น เพื่อพิจารณาว่าจะฆ่ากระบวนการใดเมื่อหน่วยความจำเหลือน้อย กระบวนการเหล่านี้จัดตามลําดับความสําคัญดังนี้

  1. กระบวนการที่ทำงานอยู่เบื้องหน้าคือกระบวนการที่จําเป็นสําหรับสิ่งที่ผู้ใช้กําลังทําอยู่ คอมโพเนนต์แอปพลิเคชันต่างๆ อาจทําให้ระบบพิจารณากระบวนการที่รวมอยู่นั้นอยู่เบื้องหน้าในลักษณะต่างๆ ระบบจะถือว่ากระบวนการทำงานอยู่เบื้องหน้าหากเป็นไปตามเงื่อนไขข้อใดข้อหนึ่งต่อไปนี้
    • มีการเรียกใช้ Activity ที่ด้านบนของหน้าจอที่ผู้ใช้โต้ตอบอยู่ (มีการเรียกใช้เมธอด onResume())
    • มี BroadcastReceiver ที่กําลังทํางานอยู่ (วิธีการ BroadcastReceiver.onReceive() ดําเนินการอยู่)
    • เพราะมี Service ที่กําลังเรียกใช้โค้ดในหนึ่งในคอลแบ็ก (Service.onCreate(), Service.onStart() หรือ Service.onDestroy())
  2. ระบบจะมีกระบวนการดังกล่าวเพียงไม่กี่รายการเท่านั้น และระบบจะหยุดกระบวนการเหล่านี้ก็ต่อเมื่อเป็นทางเลือกสุดท้ายในกรณีที่หน่วยความจําเหลือน้อยมากจนแม้แต่กระบวนการเหล่านี้ยังทํางานต่อไปไม่ได้ โดยทั่วไปแล้ว หากเกิดเหตุการณ์นี้ขึ้น แสดงว่าอุปกรณ์อยู่ในสถานะการแบ่งหน่วยความจำ จึงจำเป็นต้องดำเนินการนี้เพื่อให้อินเทอร์เฟซผู้ใช้ตอบสนองได้อยู่เสมอ

  3. กระบวนการที่มองเห็นได้จะทํางานตามที่ผู้ใช้รับรู้อยู่ในปัจจุบัน การสิ้นสุดกระบวนการดังกล่าวจึงส่งผลเสียต่อประสบการณ์ของผู้ใช้อย่างชัดเจน ระบบจะถือว่ากระบวนการมองเห็นได้ในเงื่อนไขต่อไปนี้
    • มีการเรียกใช้ Activity ที่ผู้ใช้มองเห็นบนหน้าจอแต่ไม่ได้อยู่ในเบื้องหน้า (มีการเรียกใช้เมธอด onPause()) กรณีนี้อาจเกิดขึ้นได้ เช่น หาก Activity ที่อยู่เบื้องหน้าแสดงเป็นกล่องโต้ตอบที่มองเห็น Activity ก่อนหน้าอยู่เบื้องหลัง
    • แอปมี Service ที่ทำงานเป็นบริการที่ทำงานอยู่เบื้องหน้าผ่าน Service.startForeground() (ซึ่งขอให้ระบบถือว่าบริการเป็นสิ่งที่ผู้ใช้รับรู้ หรือโดยพื้นฐานแล้วราวกับว่ามองเห็นบริการนั้น)
    • บริการนี้โฮสต์บริการที่ระบบใช้สำหรับฟีเจอร์บางอย่างที่ผู้ใช้ทราบ เช่น วอลเปเปอร์เคลื่อนไหวหรือบริการวิธีการป้อนข้อมูล

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

  4. กระบวนการบริการคือกระบวนการที่มี Service ที่เริ่มต้นด้วยเมธอด startService() แม้ว่าผู้ใช้จะไม่เห็นกระบวนการเหล่านี้โดยตรง แต่โดยทั่วไปแล้วกระบวนการเหล่านี้จะทําสิ่งที่ผู้ใช้สนใจ (เช่น การอัปโหลดหรือดาวน์โหลดข้อมูลเครือข่ายในเบื้องหลัง) ดังนั้นระบบจะทําให้กระบวนการดังกล่าวทํางานอยู่เสมอ เว้นแต่ว่าจะมีหน่วยความจําไม่เพียงพอที่จะเก็บกระบวนการที่ทำงานอยู่เบื้องหน้าและกระบวนการที่มองเห็นได้ทั้งหมด

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

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

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

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

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

    กระบวนการที่แคชไว้มักจะเก็บอินสแตนซ์ Activity อย่างน้อย 1 รายการที่ผู้ใช้ไม่เห็นในขณะนี้ (มีการเรียกใช้เมธอด onStop() แล้วและแสดงผลแล้ว) ตราบใดที่นักพัฒนาแอปใช้วงจรชีวิตของ Activity อย่างถูกต้อง เมื่อระบบหยุดกระบวนการดังกล่าว ประสบการณ์ของผู้ใช้เมื่อกลับมาที่แอปนั้นจะไม่ได้รับผลกระทบ ระบบจะกู้คืนสถานะที่บันทึกไว้ก่อนหน้านี้ได้เมื่อกิจกรรมที่เกี่ยวข้องสร้างขึ้นใหม่ในกระบวนการใหม่ โปรดทราบว่าระบบไม่รับประกันว่าจะมีการเรียกใช้ onDestroy() ในกรณีที่ระบบหยุดกระบวนการ ดูรายละเอียดเพิ่มเติมได้ที่ Activity

    ตั้งแต่ Android 13 เป็นต้นไป กระบวนการของแอปอาจได้รับเวลาดำเนินการแบบจำกัดหรือไม่ได้รับเวลาดำเนินการเลยจนกว่าจะเข้าสู่สถานะวงจรการทำงานที่ใช้งานอยู่อย่างใดอย่างหนึ่งข้างต้น

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

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

นอกจากนี้ ระบบอาจเพิ่มลําดับความสําคัญของกระบวนการตามลําดับความสําคัญของกระบวนการอื่นที่มีต่อกระบวนการนั้น ตัวอย่างเช่น หากกระบวนการ ก. เชื่อมโยงกับ Service ที่มี Flag Context.BIND_AUTO_CREATE หรือใช้ ContentProvider ในกระบวนการ ข. การจัดประเภทของกระบวนการ ข. จะมีความสำคัญอย่างน้อยเท่ากับกระบวนการ ก. เสมอ