START_STICKY และ START_NOT_STICKY


คำตอบ:


371

รหัสทั้งสองนั้นจะเกี่ยวข้องเมื่อโทรศัพท์มีหน่วยความจำไม่เพียงพอและฆ่าบริการก่อนที่จะดำเนินการเสร็จสิ้น START_STICKYบอกให้ระบบปฏิบัติการสร้างบริการขึ้นมาใหม่หลังจากที่มีหน่วยความจำเพียงพอและโทรonStartCommand()อีกครั้งด้วยเจตนาว่างเปล่า START_NOT_STICKYแจ้งให้ระบบปฏิบัติการไม่ต้องสร้างบริการอีกครั้ง นอกจากนี้ยังมีรหัสที่สามSTART_REDELIVER_INTENTที่บอกให้ระบบปฏิบัติการสร้างบริการขึ้นใหม่และส่งมอบเจตนาเดิมonStartCommand()อีกครั้ง

บทความโดย Dianne Hackborn อธิบายพื้นหลังของเรื่องนี้ดีกว่าเอกสารอย่างเป็นทางการ

ที่มา: http://android-developers.blogspot.com.au/2010/02/service-api-changes-starting-with.html

ส่วนสำคัญที่นี่คือรหัสผลลัพธ์ใหม่ที่ส่งคืนโดยฟังก์ชั่นโดยบอกระบบว่าควรทำอย่างไรกับบริการหากกระบวนการถูกฆ่าขณะที่กำลังทำงาน:

START_STICKY นั้นเหมือนกันกับพฤติกรรมที่ผ่านมาซึ่งเป็นบริการที่ "เริ่มต้น" และระบบจะเริ่มต้นใหม่ในภายหลัง ข้อแตกต่างจากแพลตฟอร์มรุ่นก่อนหน้าคือหากได้รับการเริ่มต้นใหม่เนื่องจากกระบวนการถูกฆ่า onStartCommand () จะถูกเรียกใช้ในอินสแตนซ์ถัดไปของบริการด้วยเจตนาแบบ null แทนที่จะไม่ถูกเรียกเลย บริการที่ใช้โหมดนี้ควรตรวจสอบกรณีนี้และจัดการกับมันอย่างเหมาะสม

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

START_REDELIVER_INTENT นั้นเป็นเหมือน START_NOT_STICKY ยกเว้นว่ากระบวนการของบริการนั้นถูกฆ่าก่อนที่มันจะหยุด stopSelf () เพื่อจุดประสงค์ที่กำหนดความตั้งใจนั้นจะถูกส่งอีกครั้งจนกว่าจะเสร็จสมบูรณ์ (เว้นแต่หลังจากพยายามอีกหลายครั้งก็ยังไม่เสร็จสมบูรณ์ ตรงจุดที่ระบบยอมแพ้) สิ่งนี้มีประโยชน์สำหรับบริการที่รับคำสั่งงานที่ต้องทำและต้องการให้แน่ใจว่าในที่สุดพวกเขาจะทำงานให้เสร็จสมบูรณ์สำหรับแต่ละคำสั่งที่ส่ง


1
วิธีหลีกเลี่ยงการเรียกซ้ำไปที่ task handleStart (เจตนา, startId); ในฐานะที่เป็นทั้ง onStart () และ onStartCommand จะถูกเรียก? มันเป็นการออกแบบที่ดีหรือไม่? @ Frank Leigh
Sazzad Hissain Khan

2
แม้ว่าแฟล็กเริ่มต้นคืออะไรหากไม่มีการระบุไว้
IgorGanapolsky

3
หากคุณทำตาม "return super.onStartCommand (... );" คุณจะเห็นว่าในกรณีที่รุ่น sdk เป้าหมายของคุณน้อยกว่า ECLAIR (API5 = 2.0) โดยค่าเริ่มต้น START_STICKY_COMPATIBILITY จะถูกส่งคืนและจาก 2.0 ขึ้นไปจะถูกส่งคืน START_STICKY
MikeL

1
คุณหมายถึงอะไรโดย "ไม่มีคำสั่งเริ่มต้นที่เหลือ" ในSTART_NOT_STICKY?
Malwinder Singh

3
@ FrankLeigh ฉันไม่เห็นด้วยที่START_REDELIVER_INTENTเป็นเช่นSTART_NOT_STICKYนั้น แต่มันเป็นเหมือนSTART_STICKY
CopsOnRoad

107

จูบตอบ

ความแตกต่าง:

START_STICKY

ระบบจะพยายามสร้างบริการของคุณใหม่หลังจากที่ถูกฆ่าแล้ว

START_NOT_STICKY

ระบบจะไม่พยายามสร้างบริการของคุณใหม่หลังจากถูกฆ่า


ตัวอย่างมาตรฐาน:

@Override
public int onStartCommand(Intent intent, int flags, int startId) {
    return START_STICKY;
}

5
สิ่งนี้ไม่ถูกต้องและสับสน มันเป็นความผิดพลาดที่บอกว่า: "service is kill" เนื่องจากมีใครคิดว่าคุณอ้างถึง stopSelf หรือ stopService ในขณะที่คุณอ้างถึงกระบวนการที่ถูกฆ่า ดังนั้นคุณควรใช้กระบวนการคำในคำตอบของคุณ
Ilya Gazman

สวัสดีฉันจะทดสอบSTART_REDELIVER_INTENTได้อย่างไร ฉันเพิ่งทดสอบSTART_STICKYและฆ่าแอพโดยแอพล่าสุด จากนั้นจะเรียกคืนบริการ แต่START_REDELIVER_INTENTไม่เคยเรียกอีกครั้ง ทำไม?
Asif Mushtaq

@IlyaGazman ฉันไม่เห็นด้วยอย่างเคารพ การหยุดและฆ่าเป็นคำสองคำที่แตกต่างกันมาก คำตอบนี้อธิบายปัญหาได้อย่างถูกต้องในวิธีที่ง่ายและตรงไปตรงมา
NoHarmDan

23

เอกสารสำหรับSTART_STICKYและSTART_NOT_STICKYค่อนข้างตรงไปตรงมา

START_STICKY:

หากกระบวนการของบริการนี้ถูกฆ่าตายในขณะที่มันเริ่มต้น (หลังจากกลับมาจากonStartCommand(Intent, int, int))นั้นปล่อยให้มันอยู่ในสถานะที่เริ่มต้น แต่ไม่ได้เก็บไว้เจตนาที่ส่งมอบในภายหลังระบบจะพยายามสร้างบริการอีกครั้งเพราะมันอยู่ในสถานะเริ่มต้น มันจะรับประกันว่าจะโทรonStartCommand(Intent, int, int) หลังจากที่สร้างอินสแตนซ์บริการใหม่หากไม่มีคำสั่งเริ่มต้นที่รอดำเนินการที่จะส่งมอบให้กับบริการมันจะถูกเรียกด้วยวัตถุเจตนาเป็นโมฆะดังนั้นคุณจะต้องตรวจสอบเรื่องนี้ด้วย

โหมดนี้เหมาะสมสำหรับสิ่งต่าง ๆ ที่จะเริ่มต้นอย่างชัดเจนและหยุดเพื่อให้ทำงานตามระยะเวลาที่กำหนดเช่นบริการเล่นเพลงพื้นหลัง

ตัวอย่าง: ตัวอย่างบริการท้องถิ่น

START_NOT_STICKY:

ถ้ากระบวนการของบริการนี้ถูกฆ่าตายในขณะที่มีการเริ่มต้น (หลังจากกลับมาจากonStartCommand(Intent, int, int))และไม่มีเจตนาเริ่มต้นใหม่ในการส่งมอบไปแล้วใช้บริการออกจากรัฐที่ตั้งขึ้นและไม่สร้างจนกว่าจะมีการโทรอย่างชัดเจนในอนาคต Context.startService(Intent). บริการ จะไม่ได้รับการ onStartCommand(Intent, int, int)โทรด้วยnullเจตนาเพราะจะไม่สามารถเริ่มต้นใหม่ได้หากไม่มีความตั้งใจที่รอส่ง

โหมดนี้เหมาะสมสำหรับสิ่งที่ต้องการทำงานบางอย่างอันเป็นผลมาจากการเริ่มต้น แต่สามารถหยุดได้เมื่ออยู่ภายใต้แรงกดดันหน่วยความจำและจะเริ่มต้นตัวเองอีกครั้งในภายหลังเพื่อทำงานให้ชัดเจนยิ่งขึ้น ตัวอย่างของบริการดังกล่าวจะเป็นสิ่งที่โพลสำหรับข้อมูลจากเซิร์ฟเวอร์: มันสามารถกำหนดเวลาการเตือนภัยเพื่อสำรวจความคิดเห็นทุก ๆNนาทีโดยให้การเตือนเริ่มต้นบริการ เมื่อonStartCommand(Intent, int, int)ถูกเรียกจากการเตือนภัยจะกำหนดเวลาการเตือนใหม่เป็นเวลา N นาทีต่อมาและวางไข่เธรดเพื่อสร้างเครือข่าย หากกระบวนการถูกฆ่าตายในขณะที่ทำการตรวจสอบนั้นบริการจะไม่ถูกรีสตาร์ทจนกว่าสัญญาณเตือนจะดับ

ตัวอย่าง: ServiceStartArguments.java


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

สำหรับ START_STICKY และ START_NOT_STICKY บน StartCommand () จะถูกดำเนินการเพียงครั้งเดียวและออกมา ฉันผ่านตัวอย่างที่ชี้ไปแล้ว แต่ข้อสงสัยของฉันคือกี่ครั้งที่ onStartCommand () จะถูกประหารชีวิต ถ้าฉันเริ่มต้นใหม่ START_STICKY และยังคงพยายามสร้างบริการอีกครั้งบริการจะดำเนินการบน StartCommand หรือไม่
prago

จะเกิดอะไรขึ้นกับกิจกรรมเมื่อสร้างบริการขึ้นใหม่ กิจกรรมถูกสร้างขึ้นอีกครั้งหรือไม่
ransh

ฉันเดาว่าเราจะไม่มีทางรู้
Denny
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.