Android: AsyncTask vs Dịch vụ


138

Tại sao tôi đọc trong câu trả lời cho hầu hết các câu hỏi ở đây rất nhiều về AsyncTask và Trình tải nhưng không có gì về Dịch vụ ? Có phải các Dịch vụ không được biết rõ hoặc chúng bị phản đối hoặc có một số thuộc tính xấu hoặc một cái gì đó? Sự khác biệt là gì?

(Nhân tiện, tôi biết rằng có những chủ đề khác về nó, nhưng không có chủ đề nào thực sự nêu rõ sự khác biệt giúp nhà phát triển dễ dàng quyết định liệu anh ta nên sử dụng cái này hay cái kia cho một vấn đề thực tế.)

Câu trả lời:


272

Trong một số trường hợp, có thể hoàn thành cùng một nhiệm vụ với một AsyncTaskhoặc Servicetuy nhiên thường thì một nhiệm vụ phù hợp hơn với một nhiệm vụ so với nhiệm vụ khác.

AsyncTasks được thiết kế cho các tác vụ tiêu tốn thời gian một lần không thể chạy của luồng UI. Một ví dụ phổ biến là tìm nạp / xử lý dữ liệu khi nhấn nút.

Services được thiết kế để liên tục chạy trong nền. Trong ví dụ ở trên về tìm nạp dữ liệu khi nhấn nút, bạn có thể bắt đầu dịch vụ, để cho nó tìm nạp dữ liệu và sau đó dừng dữ liệu, nhưng điều này không hiệu quả. Nó nhanh hơn nhiều để sử dụng một AsyncTaskcái sẽ chạy một lần, trả lại dữ liệu và được thực hiện.

Tuy nhiên, nếu bạn cần liên tục làm một cái gì đó trong nền, thì đó Servicelà đặt cược tốt nhất của bạn. Ví dụ về điều này bao gồm phát nhạc, liên tục kiểm tra dữ liệu mới, v.v.

Ngoài ra, như Sherif đã nói, các dịch vụ không nhất thiết phải chạy khỏi luồng UI.

Đối với hầu hết các phần, Services là khi bạn muốn chạy mã ngay cả khi ứng dụng của bạn Activitykhông mở. AsyncTasks được thiết kế để thực hiện mã thực thi khỏi luồng UI đơn giản đến không ngờ.


2
Điều thú vị là trong cuộc nói chuyện này từ Google I / O năm 2010 youtube.com/watch?v=xHXn3Kg2IQE, người thuyết trình đưa ra 3 phương pháp khác nhau để nhận dữ liệu từ API REST và phương thức đầu tiên sử dụng dịch vụ. Tôi không phải là chuyên gia về Android nhưng tôi cũng có ấn tượng rằng những gì Computerish nói về cơ bản là chính xác.
wuliwong

10
Đoạn cuối cùng, "Dịch vụ dành cho khi bạn muốn chạy mã ngay cả khi Hoạt động của ứng dụng của bạn không mở". Đây cũng là trường hợp với AsyncTask hoặc chủ đề nền. tức là khi bạn nhấn lại hoạt động hoặc kết thúc cuộc gọi () và hoạt động của bạn không hiển thị, nhưng vẫn xử lý các luồng nền của bạn cho đến khi bạn giết tiến trình ứng dụng của mình (ví dụ: bằng cách hoán đổi từ các tác vụ gần đây). Tôi đã kiểm tra điều này với cá mú Google Nexus AOSP 4.4.2
Shirish Herwade 16/07/14

10
Tuy nhiên, AsyncTask có thể khó khăn nếu Activity bắt đầu bị hủy trong khi AsyncTask vẫn đang chạy và cần cập nhật giao diện người dùng sau khi hoàn thành ... (sẽ không hoạt động vì Activity đã bị hủy). Tại sao không sử dụng IntentService mà bạn không cần dừng thủ công, vì đơn giản là nó kết thúc sau khi hoàn thành?
Đặc vụKnopf

điểm tuyệt vời. Giải thích tốt về dịch vụ. Đó là dịch vụ chạy trong nền liên tục ngay cả khi công việc được thực hiện.
BABU K

3
@LarsH Sửa lỗi cho tôi nếu tôi sai, nhưng tôi nghĩ rằng bạn có thể sử dụng BroadcastReceiver trong Activity / Fragment của bạn và từ IntentService bạn chỉ cần phát Broadcast sau khi hoàn thành. Vì bạn có thể đăng ký lại Phát sóng khi tạo lại Hoạt động / Đoạn mà bạn nên bảo hiểm. Một cách khác là sử dụng EventBus để cập nhật giao diện người dùng (mặc dù tôi cố gắng tránh những thứ đó - làm cho mã khó theo dõi imo hơn).
Đặc vụKnopf

58

Dịch vụ hoàn toàn khác nhau: Dịch vụ không phải là chủ đề !

Hoạt động của bạn liên kết với một dịch vụ và dịch vụ chứa một số chức năng mà khi được gọi, sẽ chặn chuỗi cuộc gọi. Dịch vụ của bạn có thể được sử dụng để thay đổi nhiệt độ từ Celsius sang Độ. Bất kỳ hoạt động liên kết có thể có được dịch vụ này.


Tuy nhiên, AsyncTaskmột Chủ đề thực hiện một số hoạt động ở chế độ nền và đồng thời có khả năng báo cáo kết quả về chuỗi cuộc gọi.

Chỉ cần một suy nghĩ: Một dịch vụ có thể có một AsyncTaskđối tượng!


2
Các dịch vụ được mô tả là đang chạy trong nền, mặc dù vẫn tiếp tục ngay cả khi đóng ứng dụng của bạn. AsyncTask cũng được sử dụng để làm một cái gì đó trong nền. Biết ý tôi không?
erikbwork

1
yeah nhưng dịch vụ có thể hoặc không thể làm một cái gì đó. Chúng là một ĐỐI TƯỢNG lâu dài
Sherif elKhatib

"Một dịch vụ có thể có đối tượng AsyncTask!" Cảm ơn đã chỉ ra rằng. Nhưng nó có phải là một ý tưởng tốt - nó có phải là thứ bạn muốn giới thiệu không? Hoặc sẽ tốt hơn nếu sử dụng các kỹ thuật phân luồng cơ bản hơn trong một dịch vụ?
RenniePet

"Hoạt động của bạn liên kết với một dịch vụ" không nhất thiết phải như vậy.
JacksOnF1re

@ JacksOnF1re Tôi biết điều này giống như khi tôi mới bắt đầu viết mã: p nhưng "Hoạt động của bạn liên kết với một dịch vụ" là một tuyên bố đúng. Tôi cũng có thể ràng buộc với dịch vụ này. Một tủ lạnh cũng có thể được ràng buộc. Điều này không làm cho tuyên bố không hợp lệ .. dù sao jk
Sherif elKhatib

7

Servicelà một trong những thành phần của khung Android, không yêu cầu UI thực thi, có nghĩa là ngay cả khi ứng dụng không được người dùng sử dụng tích cực, bạn có thể thực hiện một số thao tác với dịch vụ. Điều đó không có nghĩa là dịch vụ sẽ chạy trong một luồng riêng biệt, nhưng nó chạy trong luồng chính và hoạt động có thể được thực hiện trong một luồng riêng khi cần. Ví dụ cách sử dụng đang phát nhạc ở chế độ nền, đồng bộ hóa dữ liệu với máy chủ trong backgroud mà không có sự tương tác của người dùng, v.v.

AsyncTaskmặt khác được sử dụng cho các tác vụ chặn UI được thực hiện trên một luồng riêng biệt. Nó cũng giống như tạo một luồng mới và thực hiện nhiệm vụ khi tất cả các tác vụ tạo và duy trì các luồng và gửi lại kết quả cho luồng chính được sử dụng bởi AsyncTask Ví dụ sử dụng đang tìm nạp dữ liệu từ máy chủ, các thao tác CRUD trên trình phân giải nội dung, v.v.


bạn có thể chỉ định lý do tại sao bạn nghĩ rằng câu trả lời của bạn thêm bất cứ điều gì vào câu hỏi?
erikbwork

2
những câu trả lời khác quá ngắn hoặc quá dài để người mới bắt đầu hiểu. vì vậy tôi đã trả lời chính xác bằng những từ đơn giản với các ví dụ
arjun

6

Dịch vụasynctasks gần như làm điều tương tự, hầu hết .using dịch vụ hoặc một AsyncTask phụ thuộc vào những gì là yêu cầu của bạn.

như một ví dụ nếu bạn muốn tải dữ liệu vào listview từ máy chủ sau khi nhấn nút hoặc thay đổi màn hình, tốt nhất bạn nên sử dụng asynctask.it chạy song song với luồng ui chính (chạy trong nền). Để chạy hoạt động asynctack hoặc ứng dụng của bạn nên trên chủ đề UI chính. Sau khi thoát khỏi ứng dụng, không có asynctask.

Nhưng các dịch vụ không như vậy, một khi bạn bắt đầu một dịch vụ, nó có thể chạy sau khi bạn thoát khỏi ứng dụng, trừ khi bạn dừng dịch vụ. Như tôi đã nói, nó phụ thuộc vào yêu cầu của bạn. Nếu bạn muốn tiếp tục kiểm tra nhận dữ liệu hoặc kiểm tra trạng thái mạng liên tục bạn tốt hơn đi với dịch vụ.

hạnh phúc mã hóa.


1
Xin chào Ashana, tôi có thể hỏi tại sao bạn cung cấp câu trả lời này cho một câu hỏi đã được trả lời không? Bạn không hài lòng với câu trả lời được đánh dấu hiện có? Hay bạn cố gắng xây dựng một hồ sơ SO bằng cách viết ý kiến ​​của bạn cho tất cả các câu hỏi mà bạn có điều gì muốn nói? Hay một cái gì đó hoàn toàn khác nhau? Không thể tìm ra nó, nhưng tôi thấy mô hình đó khá thường xuyên gần đây.
erikbwork

3
ya tôi biết câu trả lời đã được đưa ra và tôi không thấy nhiều vấn đề ở đây nếu tôi đưa ra câu trả lời đúng hoặc ý kiến ​​của tôi ở đây bro? bởi vì bạn không phải là người duy nhất tìm kiếm câu trả lời cho cùng một câu hỏi, nếu ai đó khó hiểu giải pháp trong câu trả lời trên, anh ấy / cô ấy có thể cuộn xuống để tìm câu trả lời phù hợp với họ, dễ dàng hiểu được. Cảm ơn các bạn đã bình luận, tôi không phải là thiên tài hay chuyên gia lập trình, chỉ muốn giúp đỡ người khác, cố gắng dạy cho người khác những gì tôi đã biết :)
Ashana.Jackol

1

Trong vài trường hợp, bạn có thể đạt được cùng một chức năng bằng cách sử dụng cả hai. Không giống như Nhiệm vụ Async, dịch vụ có vòng đời riêng và kế thừa Ngữ cảnh (Dịch vụ mạnh hơn Nhiệm vụ Async). Dịch vụ có thể chạy ngay cả khi bạn đã thoát khỏi ứng dụng. Nếu bạn muốn làm một cái gì đó ngay cả sau khi đóng ứng dụng và cũng cần biến bối cảnh, bạn sẽ tìm đến Dịch vụ.

Ví dụ: Nếu bạn muốn phát nhạc và bạn không muốn tạm dừng nếu người dùng rời khỏi ứng dụng, bạn chắc chắn sẽ truy cập Dịch vụ.


1

So sánh một dịch vụ lớp cơ sở, đang xử lý, cục bộ ✱ với AsyncTask:

✱ (Câu trả lời này không đề cập đến các dịch vụ xuất khẩu, hoặc bất kỳ dịch vụ nào chạy trong một quy trình khác với dịch vụ của khách hàng, vì các trường hợp sử dụng dự kiến ​​khác biệt đáng kể với các dịch vụ của AsyncTask. Ngoài ra, về lợi ích của sự ngắn gọn, bản chất của một số chuyên ngành nhất định Servicelớp con (ví dụ IntentService, JobService) sẽ bị bỏ qua ở đây.)

Quá trình suốt đời

A Serviceđại diện cho HĐH, "mong muốn của ứng dụng là thực hiện thao tác chạy lâu hơn trong khi không tương tác với người dùng" [ ref ].

Trong khi bạn có một Service đang chạy, Android hiểu rằng bạn không muốn quá trình của mình bị giết. Điều này cũng đúng bất cứ khi nào bạn có một Activitymàn hình và điều này đặc biệt đúng khi bạn đang chạy một dịch vụ nền trước . (Khi tất cả các thành phần ứng dụng của bạn biến mất, Android nghĩ, "Ồ, bây giờ là thời điểm tốt để giết ứng dụng này, vì vậy tôi có thể giải phóng tài nguyên".)

Ngoài ra, tùy thuộc vào giá trị trả lại cuối cùng từ Service.onCreate() , Android có thể cố gắng "hồi sinh" các ứng dụng / dịch vụ đã bị hủy do áp lực tài nguyên [ ref ].

AsyncTasksđừng làm điều đó Không quan trọng bạn đang chạy bao nhiêu luồng nền hay chúng hoạt động mạnh đến mức nào: Android sẽ không giữ ứng dụng của bạn tồn tại chỉ vì ứng dụng của bạn đang sử dụng CPU. Nó phải có một số cách biết rằng ứng dụng của bạn vẫn còn việc phải làm; đó là lý do tại sao Servicesđược đăng ký với HĐH và AsyncTaskskhông.

Đa luồng

AsyncTasks tất cả là về việc tạo ra một luồng nền để thực hiện công việc, và sau đó trình bày kết quả của công việc đó cho luồng UI theo cách an toàn của luồng.

Mỗi lần AsyncTaskthực hiện mới thường dẫn đến nhiều đồng thời hơn (nhiều luồng hơn), tuân theo các giới hạn của nhóm AsyncTasks'sluồng [ ref ].

Servicemặt khác, các phương thức luôn được gọi trên luồng UI [ ref ]. Này áp dụng cho onCreate(), onStartCommand(), onDestroy(), onServiceConnected(), vv Vì vậy, trong một nghĩa nào đó, Serviceskhông "chạy" ở chế độ nền. Khi họ bắt đầu (onCreate() ), họ chỉ cần "ngồi" ở đó - cho đến khi dọn dẹp, thực hiện mộtonStartCommand() , v.v.

Nói cách khác, việc thêm bổ sung Serviceskhông dẫn đến đồng thời nhiều hơn. Các phương thức dịch vụ không phải là nơi tốt để thực hiện một lượng lớn công việc, vì chúng chạy trên luồng UI .

Tất nhiên, bạn có thể mở rộng Service, thêm các phương thức của riêng bạn và gọi chúng từ bất kỳ luồng nào bạn muốn. Nhưng nếu bạn làm điều đó, trách nhiệm về an toàn luồng sẽ thuộc về bạn - không phải là khung.

Nếu bạn muốn thêm một chủ đề nền (hoặc một số loại công nhân khác) cho bạn Service, bạn có thể tự do làm điều đó. Bạn có thể bắt đầu một sợi nền / AsyncTasktrong Service.onCreate(), ví dụ. Nhưng không phải tất cả các trường hợp sử dụng đều yêu cầu điều này. Ví dụ:

  • Bạn có thể muốn tiếp tục Servicechạy để bạn có thể tiếp tục nhận được cập nhật vị trí trong "nền" (nghĩa là không nhất thiết phải có bất kỳ Activitiesmàn hình nào ).
  • Hoặc, bạn có thể muốn giữ cho ứng dụng của mình tồn tại chỉ để bạn có thể giữ một "ẩn" được BroadcastReceiverđăng ký trên cơ sở lâu dài (sau API 26, bạn không thể luôn thực hiện việc này qua bảng kê khai, vì vậy bạn phải đăng ký khi chạy [ ref ]).

Cả hai trường hợp sử dụng này đều yêu cầu rất nhiều hoạt động của CPU; họ chỉ yêu cầu ứng dụng không bị giết .

Là công nhân

Serviceskhông định hướng nhiệm vụ. Họ không được thiết lập để "thực hiện một nhiệm vụ" và "cung cấp một kết quả", giống như AsyncTaskslà. Serviceskhông giải quyết bất kỳ vấn đề an toàn luồng nào (mặc dù thực tế là tất cả các phương thức thực thi trên một luồng). AsyncTasksmặt khác, xử lý sự phức tạp đó cho bạn.

Lưu ý rằng AsyncTaskđược dự kiến sẽ deprecation . Nhưng điều đó không có nghĩa là bạn nên thay thế AsyncTasksbằng Services! (Nếu bạn đã học được bất cứ điều gì từ câu trả lời này, điều đó sẽ rõ ràng.)

TL; DR

Serviceschủ yếu là ở đó để "tồn tại". Chúng giống như một màn hình ngoài Activity, cung cấp một lý do để ứng dụng tồn tại, trong khi các thành phần khác đảm nhận việc thực hiện "công việc". AsyncTaskslàm "công việc", nhưng bản thân họ sẽ không giữ cho một quá trình tồn tại.

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.