Xử lý vs AsyncTask


128

Tôi bối rối không biết khi nào người ta sẽ chọn AsyncTask thay cho Handler. Nói rằng tôi có một số mã tôi muốn chạy mỗi n giây sẽ cập nhật giao diện người dùng. Tại sao tôi lại chọn cái này?


1
Điều này đã trở nên phức tạp hơn với AsyncTaskLoaders. Xem stackoverflow.com/q/7120813/969325 để biết thêm thông tin.
Warpzit

Câu trả lời:


75

IMO, AsyncTask được viết để cung cấp một cách thuận tiện, dễ sử dụng để đạt được xử lý nền trong các ứng dụng Android, mà không phải lo lắng quá nhiều về các chi tiết cấp thấp (chủ đề, vòng lặp thông báo, v.v.). Nó cung cấp các phương thức gọi lại giúp lên lịch các tác vụ và cũng dễ dàng cập nhật giao diện người dùng bất cứ khi nào cần thiết.

Tuy nhiên, điều quan trọng cần lưu ý là khi sử dụng AsyncTask, nhà phát triển đang tuân theo các giới hạn của nó, điều này dẫn đến các quyết định thiết kế mà tác giả của lớp đã đưa ra. Ví dụ, gần đây tôi phát hiện ra rằng có giới hạn số lượng công việc có thể được lên lịch bằng AsyncT task.

Handler minh bạch hơn trong hai và có thể giúp bạn tự do hơn; vì vậy nếu bạn muốn kiểm soát nhiều hơn những thứ bạn sẽ chọn Handler nếu không AsynTask sẽ hoạt động tốt.


Đúng rồi. Tôi đã sử dụng AsyncT task cho tất cả các hoạt động nền trong dự án của mình. Tại một số thời điểm tôi bắt đầu đạt đến giới hạn công việc tối đa đó, vì vậy các nhiệm vụ của tôi sẽ chỉ bắt đầu sau khi hoàn thành một công việc khác. Cuối cùng, tôi đã phải thay đổi tất cả cấu trúc của mình để ngừng sử dụng các tác vụ phụ và tránh đạt đến giới hạn đó.
tbraun

5
Từ Honeycomb trở đi, AsyncTasksđược thực thi trên một luồng, do đó không còn song song nữa. Bạn vẫn có thể chạy chúng khi Executorthực hiện paralel .
MrSnowflower

63

Quy tắc ngón tay cái của tôi sẽ là:

  • Nếu bạn đang làm một cái gì đó tách biệt liên quan đến UI, ví dụ như tải xuống dữ liệu để trình bày trong danh sách, hãy tiếp tục và sử dụng AsyncTask.

  • Nếu bạn đang thực hiện nhiều tác vụ lặp lại, ví dụ như tải xuống nhiều hình ảnh sẽ được hiển thị trong ImageViews(như tải xuống hình thu nhỏ) khi tải xuống, hãy sử dụng hàng đợi tác vụ với Handler.


Handler đang ở API cấp 1 & ASYNCTASK ở cấp độ API 3. nó có bị phản đối với bất kỳ giá nào không? vì tôi đang tập trung vào việc chuyển các ứng dụng từ các phiên bản cũ sang 2.2 & 2.3 ..
yokks

10
Sẽ không được phản đối bất cứ lúc nào sớm. Handler sẽ không bao giờ bị phản đối vì UI được xây dựng cơ bản xung quanh nó.
alexanderblom

Bạn có nên sử dụng Trình tải để tải dữ liệu cho giao diện người dùng của mình không?
nbarraille

19

Luôn cố gắng tránh sử dụng AsyncTask khi có thể chủ yếu vì các lý do sau:

  • AsyncTask không được đảm bảo để chạy vì có một cơ sở ThreadPool và kích thước tối đa được thiết lập bởi hệ thống và nếu bạn tạo quá nhiều asynctask thì cuối cùng chúng sẽ bị hủy

  • AsyncTask có thể tự động chấm dứt, ngay cả khi đang chạy, tùy thuộc vào vòng đời hoạt động và bạn không có quyền kiểm soát đối với nó

  • Các phương thức AsyncTask chạy trên Giao diện người dùng, như onPostExecute, có thể được thực thi khi Hoạt động mà nó đề cập đến, không hiển thị nữa hoặc có thể ở trạng thái bố cục khác, như sau khi thay đổi hướng.

Tóm lại, bạn không nên sử dụng các phương thức được liên kết với UIThread của AsyncTask, đây là ưu điểm chính của nó !!! Ngoài ra, bạn chỉ nên làm công việc không quan trọng trên doInBackground. Đọc chủ đề này để hiểu thêm về vấn đề này:

Là AsyncTask thực sự thiếu sót về mặt khái niệm hay tôi chỉ thiếu một cái gì đó?

Để kết luận, hãy thử sử dụng IntentService, HandlerThread hoặc ThreadPoolExecutor thay vì AsyncTask khi bất kỳ vấn đề nào được trích dẫn ở trên làm bạn lo lắng. Chắc chắn nó sẽ đòi hỏi nhiều công việc hơn nhưng ứng dụng của bạn sẽ an toàn hơn.


Vâng, tôi đã dành rất nhiều thời gian để hối tiếc về việc sử dụng AsyncT Nhiệm vụ. Chúng có vẻ tuyệt vời, nhưng ... rất nhiều vấn đề!
Scott Biggie

6
Tôi xin lỗi vì đã đăng rất mạnh mẽ chống lại quan điểm của bạn, nhưng tôi không thể để phong cách kém hiệu quả của bạn không phù hợp với Android. Điểm một. Bạn KHÔNG nên có nhiều chủ đề đang chạy. Nếu bạn đi qua đây kiến ​​trúc của bạn là foobar. Điểm 2. Làm thế nào trên trái đất .. Được rồi, vâng, tất cả mọi thứ trong Android là trò chơi miễn phí cho người thu gom rác ... Bạn sẽ chỉ thấy hành vi lơ đãng như được mô tả ở trên, trong một số trường hợp lạm dụng nhiệm vụ nghiêm ngặt. Điểm 3. Quản lý nhiệm vụ của bạn, không thô lỗ, là một kỹ năng mới làm quen. Bạn có thể giết nó khi bạn gọi onPause, hoặc bạn tách ra và đính kèm theo.
StarWind0

1
vogella.com/tutorials/AndroidBackgroundProcessing/article.html Đây là tất cả những gì bạn cần để học cách thực hiện đúng các tác vụ mà không gặp sự cố ở trên (giả sử bạn không làm gì đó như nhổ vài trăm nhiệm vụ)
StarWind0

16

Nếu bạn muốn thực hiện phép tính mỗi x giây, có lẽ bạn nên lên lịch Runnablecho một Handler(với postDelayed()) và điều đó Runnablesẽ bắt đầu trong luồng UI hiện tại. Nếu bạn muốn bắt đầu nó trong một chủ đề khác, hãy sử dụng HandlerThread. AsyncTask dễ sử dụng hơn đối với chúng tôi nhưng không tốt hơn xử lý.


7

Handler được liên kết với luồng chính của ứng dụng. nó xử lý và lên lịch các tin nhắn và runnables được gửi từ các luồng nền đến luồng chính của ứng dụng.

AsyncTask cung cấp một phương pháp đơn giản để xử lý các luồng nền để cập nhật giao diện người dùng mà không chặn nó bởi các hoạt động tốn thời gian.

Câu trả lời là cả hai có thể được sử dụng để cập nhật giao diện người dùng từ các luồng nền, sự khác biệt sẽ nằm trong kịch bản thực hiện của bạn. Bạn có thể xem xét sử dụng trình xử lý mà bạn muốn gửi tin nhắn bị trì hoãn hoặc gửi tin nhắn đến MessageQueue theo một thứ tự cụ thể.

Bạn có thể cân nhắc sử dụng AsyncTask nếu bạn muốn trao đổi các tham số (do đó cập nhật giao diện người dùng) giữa luồng chính của ứng dụng và luồng nền theo cách dễ dàng thuận tiện.


3
Bạn có thể tạo Handler của riêng bạn được liên kết với một Thread khác.
Aleksejs Mjaliks

Handler không nhất thiết phải gắn với luồng chính (UI Thread). Nó được gắn với luồng trong đó nó đã được khởi tạo và xử lý Message's hoặc Runnable đến hàng đợi tin nhắn luồng này. Nó cũng có thể gửi các đối tượng Message và Runnable đến hàng đợi tin nhắn thread này.
azec-pdx

2

AsyncTaskgiả sử bạn sẽ làm một cái gì đó trên luồng UI, sau khi một số công việc nền kết thúc. Ngoài ra, bạn chỉ có thể thực thi nó một lần (sau đó, trạng thái của nó là FINISHEDvà bạn sẽ có một ngoại lệ khi cố gắng thực hiện nó một lần nữa). Ngoài ra, tính linh hoạt của việc sử dụng nó là không nhiều. Có, bạn có thể sử dụng THREAD_POOL_EXECUTORđể thực hiện song song, nhưng nỗ lực có thể không xứng đáng.

Handlerkhông giả định bất cứ điều gì, ngoại trừ xử lý Runnables và Tin nhắn. Ngoài ra, nó có thể được chạy nhiều lần như bạn muốn . Bạn có thể tự do quyết định nó phải được gắn vào chủ đề nào, cách nó giao tiếp với các trình xử lý khác, có thể sản xuất chúng với HandlerThread. Vì vậy, nó linh hoạt hơn nhiều và phù hợp với một số công việc lặp đi lặp lại.

Kiểm tra các loại Handlerví dụ khác nhau ở đây .


0

Họ là câu hỏi phỏng vấn tốt nhất được hỏi. AsyncTask - Chúng được sử dụng để giảm tải luồng UI và thực hiện các tác vụ trong nền. Trình xử lý - Android dosent có cách giao tiếp trực tiếp giữa UI và luồng nền. Trình xử lý phải được sử dụng để gửi tin nhắn hoặc có thể chạy qua hàng đợi tin nhắn.

Vì vậy, AsyncT task được sử dụng khi các tác vụ cần thiết được thực thi trong nền và Trình xử lý được sử dụng để liên lạc giữa UI và Chủ đề nền.


0

doInBackground - về cơ bản không hoạt động trong một chủ đề khác. onPostExecute - đăng kết quả lên luồng UI và nó đang gửi tin nhắn nội bộ đến bộ xử lý của luồng chính. Giao diện người dùng chính đã có một looper và xử lý liên kết với nó.

Vì vậy, về cơ bản, nếu bạn phải thực hiện một số tác vụ nền, hãy sử dụng AsyncTask. Nhưng cuối cùng, nếu một cái gì đó cần được cập nhật trên UI, nó sẽ sử dụng trình xử lý của luồng chính.

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.