Android: AsyncTask เทียบกับบริการ


138

ทำไมผมอ่านในคำตอบของคำถามที่นี่มากเกี่ยวกับAsyncTaskรถยกและรถ แต่ไม่มีอะไรที่เกี่ยวกับการบริการ ? บริการยังไม่เป็นที่รู้จักกันดีหรือเลิกใช้งานหรือมีคุณลักษณะที่ไม่ดีหรือบางอย่าง อะไรคือความแตกต่าง?

(โดยวิธีการที่ฉันรู้ว่ามีหัวข้ออื่น ๆ เกี่ยวกับเรื่องนี้ แต่ไม่มีใครระบุความแตกต่างที่ชัดเจนจริง ๆ ที่ช่วยให้นักพัฒนาตัดสินใจได้อย่างง่ายดายว่าเขาจะดีกว่าการใช้อย่างใดอย่างหนึ่งหรืออื่น ๆ สำหรับปัญหาจริง)

คำตอบ:


272

ในบางกรณีมันเป็นไปได้ที่จะทำภารกิจเดียวกันให้สำเร็จด้วยการทำแบบใดแบบหนึ่งAsyncTaskหรือแบบServiceปกติ

AsyncTasks ถูกออกแบบมาสำหรับงานที่ต้องใช้เวลานานซึ่งไม่สามารถรันของเธรด UI ได้ ตัวอย่างทั่วไปคือการดึง / ประมวลผลข้อมูลเมื่อกดปุ่ม

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

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

นอกจากนี้ตามที่ Sherif ได้กล่าวแล้วบริการไม่จำเป็นต้องหลุดออกจากเธรด UI

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


2
เป็นที่น่าสนใจว่าในการพูดคุยนี้จาก Google I / O ในปี 2010 youtube.com/watch?v=xHXn3Kg2IQEผู้นำเสนอให้ 3 วิธีที่แตกต่างกันในการรับข้อมูลจาก REST API และวิธีแรกใช้บริการ ฉันไม่ใช่ผู้เชี่ยวชาญด้าน Android แต่ฉันก็รู้สึกว่าสิ่งที่ Computerish พูดนั้นถูกต้องแล้ว
wuliwong

10
ย่อหน้าสุดท้าย "บริการนี้ใช้สำหรับเมื่อคุณต้องการเรียกใช้รหัสแม้ว่ากิจกรรมของแอปพลิเคชันของคุณจะไม่เปิด" นี่เป็นกรณีที่มี AsyncTask หรือเธรดพื้นหลัง เช่นเมื่อคุณกดกิจกรรมหรือการโทรเสร็จสิ้น () และมองไม่เห็นกิจกรรมของคุณ แต่ยังคงเธรดพื้นหลังของคุณจะทำงานจนกว่าคุณจะฆ่ากระบวนการแอปของคุณ (เช่นโดยการสลับจากงานล่าสุด) ฉันได้ตรวจสอบสิ่งนี้กับ 4.4.2 Google Nexus AOSP ปลาเก๋าแล้ว
Shirish Herwade

10
อย่างไรก็ตาม AsyncTask นั้นสามารถหากว่ากิจกรรมที่เริ่มต้นถูกฆ่าในขณะที่ AsyncTask ยังคงทำงานอยู่และจำเป็นต้องอัปเดต UI เมื่อเสร็จสิ้น ... (ซึ่งจะไม่ทำงานเนื่องจากกิจกรรมถูกทำลายไปแล้ว) ทำไมไม่ใช้ IntentService ซึ่งคุณไม่จำเป็นต้องหยุดด้วยตนเองเพราะมันจบลงทันทีเมื่อทำเสร็จแล้ว?
AgentKnopf

จุดที่ดีคำอธิบายที่ดีเกี่ยวกับการบริการนี่คือการบริการที่ทำงานในพื้นหลังอย่างต่อเนื่องแม้งานจะทำ
BABU K

3
@ LarsH แก้ไขให้ถูกต้องหากฉันทำผิด แต่ฉันคิดว่าคุณสามารถใช้ BroadcastReceiver ในกิจกรรม / ชิ้นส่วนของคุณและจาก IntentService คุณเพียงแค่ทำการออกอากาศเมื่อคุณทำเสร็จแล้ว เนื่องจากคุณสามารถลงทะเบียนใหม่สำหรับ Broadcasts ตามกิจกรรม / การสร้างแฟรกเมนต์ใหม่ที่ควรครอบคลุม อีกทางเลือกหนึ่งคือใช้ EventBus เพื่ออัปเดต UI (แม้ว่าฉันจะพยายามหลีกเลี่ยงสิ่งเหล่านั้น - ทำให้รหัสยากที่จะติดตาม imo)
AgentKnopf

58

บริการแตกต่างกันโดยสิ้นเชิง: บริการไม่ใช่หัวข้อ !

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


อย่างไรก็ตามAsyncTaskเป็นเธรดที่ทำงานในพื้นหลังและในเวลาเดียวกันมีความสามารถในการรายงานผลลัพธ์กลับไปยังเธรดการโทร

แค่คิด: บริการอาจมีAsyncTaskวัตถุ!


2
มีการอธิบายบริการต่าง ๆ ว่าทำงานในพื้นหลังโดยดำเนินการต่อแม้ว่าจะปิดแอปพลิเคชันของคุณก็ตาม AsyncTask ยังใช้เพื่อทำอะไรบางอย่างในพื้นหลัง รู้ว่าฉันหมายความว่าอย่างไร?
erikbwork

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

"บริการอาจมีวัตถุ AsyncTask!" ขอบคุณสำหรับการชี้ให้เห็นว่า แต่มันเป็นความคิดที่ดี - เป็นสิ่งที่คุณแนะนำหรือไม่ หรือจะเป็นการดีกว่าถ้าใช้เทคนิคการทำเกลียวขั้นพื้นฐานเพิ่มเติมในบริการ
RenniePet

"กิจกรรมของคุณผูกกับบริการ" ไม่จำเป็น
JacksOnF1

@ JacksOnF1 ฉันรู้ว่านี่เป็นเหมือนเมื่อฉันเริ่มเขียนโค้ดครั้งแรก: p แต่ "กิจกรรมของคุณผูกกับบริการ" เป็นคำสั่งที่แท้จริง ฉันยังสามารถผูกพันกับบริการนี้ ตู้เย็นอาจจะผูกพันเช่นกัน สิ่งนี้ไม่ได้ทำให้คำสั่งนั้นไม่ถูกต้อง .. อย่างไรก็ตาม jk
Sherif elKhatib

7

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

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


คุณสามารถระบุสาเหตุที่คุณคิดว่าคำตอบของคุณเพิ่มอะไรกับคำถามได้หรือไม่
erikbwork

2
คำตอบอื่น ๆ นั้นสั้นเกินไปหรือยาวเกินไปสำหรับผู้เริ่มต้นที่จะเข้าใจ ดังนั้นฉันจึงตอบอย่างแม่นยำด้วยคำง่ายๆพร้อมตัวอย่าง
จัน

6

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

ตัวอย่างเช่นถ้าคุณต้องการโหลดข้อมูลไปยัง listview จากเซิร์ฟเวอร์หลังจากกดปุ่มหรือเปลี่ยนหน้าจอคุณควรใช้ asynctask.it รันขนานกับเธรดหลัก ui (ทำงานในพื้นหลัง) เพื่อรันกิจกรรม asynctack หรือแอปของคุณควร บนเธรด UI หลักหลังจากออกจากแอปแล้วจะไม่มี asynctask

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

การเข้ารหัสที่มีความสุข


1
สวัสดี Ashana ฉันขอถามได้ไหมว่าทำไมคุณถึงให้คำตอบสำหรับคำถามที่ตอบไปแล้ว? คุณไม่พึงพอใจกับคำตอบที่ทำเครื่องหมายไว้หรือไม่? หรือคุณพยายามสร้างโปรไฟล์ SO โดยเขียนความคิดเห็นของคุณไปยังทุกคำถามที่คุณมีบางสิ่งที่จะพูดถึง หรือสิ่งที่แตกต่างอย่างสิ้นเชิง? ไม่สามารถเข้าใจได้ แต่ฉันเห็นรูปแบบนั้นค่อนข้างเร็ว ๆ นี้
erikbwork

3
ยาฉันรู้ว่าคำตอบได้รับแล้วและฉันไม่เห็นปัญหามากที่นี่ถ้าฉันให้คำตอบที่ถูกต้องหรือความเห็นของฉันในที่นี่ครับ? เพราะคุณไม่ใช่คนเดียวที่กำลังมองหาคำตอบของคำถามเดียวกันถ้าใครซักคนที่เข้าใจคำตอบได้ยากเขา / เธอสามารถเลื่อนลงมาเพื่อค้นหาคำตอบที่เหมาะกับพวกเขาเข้าใจได้ง่าย ขอบคุณสำหรับความคิดเห็นครับ im ไม่เป็นอัจฉริยะหรือโปรในการเขียนโปรแกรมเพียงแค่ต้องการที่จะช่วยเหลือคนอื่น ๆ พยายามที่จะสอนคนอื่น ๆ สิ่งที่ฉันรู้อยู่แล้ว :)
Ashana.Jackol

1

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

ตัวอย่าง: หากคุณต้องการเล่นเพลงและไม่ต้องการหยุดชั่วคราวหากผู้ใช้ออกจากแอปคุณจะต้องไปใช้บริการ


1

การเปรียบเทียบระดับบริการพื้นฐานระดับท้องถิ่นระหว่างดำเนินการกับAsyncTask: กับ

answer (คำตอบนี้ไม่ได้กล่าวถึงบริการที่ส่งออกหรือบริการใด ๆ ที่ดำเนินการในกระบวนการที่แตกต่างจากของลูกค้าเนื่องจากกรณีการใช้งานที่คาดหวังจะแตกต่างอย่างมากจากของAsyncTaskลูกค้านอกจากนี้เพื่อประโยชน์ของความกระชับServicesubclasses (เช่นIntentService, JobService) จะถูกละเว้นที่นี่.)

อายุการใช้งานกระบวนการ

A Serviceหมายถึงระบบปฏิบัติการ "ความต้องการของแอปพลิเคชันในการดำเนินการที่ยาวนานขึ้นโดยไม่ต้องโต้ตอบกับผู้ใช้" [ อ้างอิง ]

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

นอกจากนี้ขึ้นอยู่กับมูลค่าส่งคืนล่าสุดจากService.onCreate()Android สามารถพยายามที่จะ "ฟื้น" แอพ / บริการที่ถูกฆ่าเนื่องจากความกดดันของทรัพยากร [ อ้างอิง ]

AsyncTasksอย่าทำอย่างนั้น ไม่ว่าคุณจะใช้งานเธรดพื้นหลังจำนวนเท่าใดหรือทำงานหนักแค่ไหน: Android จะไม่ทำให้แอปของคุณมีชีวิตอยู่เพียงเพราะแอปของคุณใช้ซีพียู มันต้องมีวิธีการบางอย่างที่รู้ว่าแอปของคุณยังคงมีงานต้องทำ นั่นคือเหตุผลServicesที่ลงทะเบียนกับระบบปฏิบัติการและAsyncTasksไม่ใช่

multithreading

AsyncTasks ทั้งหมดเกี่ยวกับการสร้างเธรดพื้นหลังที่จะทำงานแล้วนำเสนอผลลัพธ์ของการทำงานนั้นไปยังเธรด UI ในรูปแบบ threadsafe

AsyncTaskการดำเนินการใหม่แต่ละครั้งโดยทั่วไปจะส่งผลให้เกิดการทำงานพร้อมกันมากขึ้น (เธรดมากขึ้น) ขึ้นอยู่กับข้อ จำกัด ของAsyncTasks'sเธรดพูล [ อ้างอิง ]

Serviceในทางกลับกันจะเรียกใช้วิธีการในเธรด UI [ อ้างอิง ] เสมอ นี้นำไปใช้onCreate(), onStartCommand(), onDestroy(), onServiceConnected()ฯลฯ ดังนั้นในความรู้สึกบางอย่างที่Servicesทำไม่ได้ "รัน" ในพื้นหลัง เมื่อพวกเขาเริ่ม ( onCreate()) พวกเขาเพียงแค่ "นั่ง" ที่นั่น - จนกว่าจะถึงเวลาที่จะทำความสะอาดดำเนินการonStartCommand()ฯลฯ

กล่าวอีกนัยหนึ่งการเพิ่มเพิ่มเติมServicesไม่ได้ทำให้เกิดการทำงานพร้อมกันมากขึ้น วิธีการบริการไม่ได้เป็นสถานที่ที่ดีที่จะทำจำนวนมากของการทำงานเพราะพวกเขาทำงานในหัวข้อ UI

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

หากคุณต้องการเพิ่มเธรดพื้นหลัง (หรือประเภทอื่น ๆ ของผู้ปฏิบัติงาน) ให้กับคุณServiceคุณมีอิสระที่จะทำเช่นนั้น คุณสามารถเริ่มด้าย / พื้นหลังAsyncTaskในService.onCreate()ตัวอย่างเช่น แต่ไม่ใช่ทุกกรณีที่จำเป็นต้องใช้สิ่งนี้ ตัวอย่างเช่น:

  • คุณอาจต้องการที่จะServiceทำงานต่อไปเพื่อให้คุณสามารถรับการอัปเดตตำแหน่งใน "พื้นหลัง" (ความหมายโดยไม่จำเป็นต้องมีActivitiesบนหน้าจอ)
  • หรือคุณอาจต้องการให้แอปของคุณยังมีชีวิตอยู่เพื่อให้คุณสามารถBroadcastReceiverลงทะเบียน"โดยนัย" ในระยะยาว (หลังจาก API 26 คุณไม่สามารถทำสิ่งนี้ได้ผ่านรายการดังนั้นคุณต้องลงทะเบียนที่รันไทม์แทน [ อ้างอิง ])

กรณีการใช้งานเหล่านี้ไม่จำเป็นต้องใช้กิจกรรม CPU อย่างมาก พวกเขาเพียงแค่ต้องการให้แอปไม่ถูกฆ่า

ในฐานะคนงาน

Servicesไม่ได้มุ่งเน้นงาน พวกเขาจะไม่ได้ตั้งค่าที่ "ดำเนินการงาน" และ "ส่งผลให้" เหมือนAsyncTasksเป็น Servicesไม่แก้ปัญหาความปลอดภัยของเธรดใด ๆ (แม้จะมีความจริงที่ว่าวิธีการทั้งหมดดำเนินการในหัวข้อเดียว) AsyncTasksในทางกลับกันจัดการกับความซับซ้อนนั้นสำหรับคุณ

ทราบว่าAsyncTaskมีการกำหนดไว้สำหรับการเลิกใช้ แต่นั่นไม่ได้หมายความว่าคุณควรแทนที่AsyncTasksด้วยServices! (หากคุณได้เรียนรู้อะไรจากคำตอบนี้จะต้องชัดเจนมาก)

TL; DR

Servicesส่วนใหญ่จะมี "มีอยู่" พวกเขาเป็นเหมือนหน้าจอปิดActivityให้เหตุผลสำหรับแอปมีชีวิตอยู่ในขณะที่ส่วนประกอบอื่น ๆ ดูแล "ทำงาน" AsyncTasksทำงาน "" แต่พวกเขาจะไม่ทำให้กระบวนการมีชีวิต

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