2010-03-26 39 views
118

Tôi bị nhầm lẫn là khi nào người dùng sẽ chọn AsyncTask trên Trình xử lý. Giả sử 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 khác?Trình xử lý vs AsyncTask

+1

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

Trả lời

70

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 ứng dụng Android mà không phải lo lắng quá nhiều về chi tiết cấp thấp (chủ đề, vòng tin nhắn, 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 yêu cầu.

Tuy nhiên, điều quan trọng cần lưu ý là khi sử dụng AsyncTask, nhà phát triển sẽ gửi đến những hạn chế của nó, kết quả là do các quyết định thiết kế mà tác giả của lớp đã thực hiện. Ví dụ: Gần đây tôi đã phát hiện ra rằng có một giới hạn về số lượng công việc có thể được lên lịch sử dụng AsyncTasks.

Trình xử lý minh bạch hơn và có thể mang đến cho bạn nhiều tự do hơn; vì vậy nếu bạn muốn kiểm soát nhiều hơn về những thứ bạn sẽ chọn Handler nếu không AsynTask sẽ hoạt động tốt.

+0

Đúng vậy. Tôi đã sử dụng AsyncTasks cho tất cả các hoạt động nền trong dự án của mình. Tại một thời điểm nào đó, tôi bắt đầu đạt đến giới hạn công việc tối đa đó, vì vậy 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 asynctask và tránh đạt tới giới hạn đó. – tbraun

+4

Từ Honeycomb on, 'AsyncTasks' được thực hiện trên một luồng, do đó không có tính song song nữa. Bạn vẫn có thể chạy chúng trên một thực thi song song 'Executor'. – MrSnowflake

14

Nếu bạn muốn thực hiện phép tính sau mỗi x giây, bạn có thể lập lịch biểu Runnable trên Handler (với postDelayed()) và rằng Runnable sẽ bắt đầu trong chuỗi giao diện người dùng 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 nhưng không tốt hơn xử lý.

+0

+1 cho HandlerThread mà tôi không biết! – Eduardo

57

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

  • Nếu bạn đang làm một cái gì đó tách biệt liên quan đến giao diện người dùng, ví dụ tải dữ liệu để trình bày trong một danh sách, đi trướ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ụ 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.

+0

Trình xử lý ở cấp API 1 & ASYNCTASK ở cấp API 3. nó sẽ không được chấp nhận với bất kỳ chi phí nào không? becaz đ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

+8

Sẽ không được chấp nhận bất kỳ lúc nào. Trình xử lý sẽ không bao giờ bị phản đối khi giao diện người dùng được xây dựng xung quanh nó. – alexanderblom

+0

Bạn không 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 để trình bày? – nbarraille

6

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

AsyncTask cung cấp một phương pháp đơn giản để xử lý các chủ đề nền để cập nhật giao diện người dùng mà không chặn nó bằng 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ừ chủ đề nền, sự khác biệt sẽ nằm trong kịch bản thực thi của bạn. Bạn có thể xem xét sử dụng trình xử lý mà bạn muốn đăng các thư bị trì hoãn hoặc gửi tin nhắn đến MessageQueue theo một thứ tự cụ thể.

Bạn có thể xem xét sử dụng AsyncTask nếu bạn muốn trao đổi thông số (do đó cập nhật giao diện người dùng) giữa chuỗi chính của ứng dụng và chuỗi nền một cách dễ dàng.

+3

Bạn có thể tạo Trình xử lý của riêng bạn được liên kết với một Chủ đề khác. –

+0

Trình xử lý không nhất thiết phải gắn với chủ đề chính (Giao diện người dùng). Nó được gắn với luồng mà nó được khởi tạo và xử lý của Message hoặc Runnable đến hàng đợi thông báo chuỗi này. Nó cũng có thể gửi các đối tượng Message và Runnable tới hàng đợi tin nhắn luồng này. – Zec

16

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

  • AsyncTask không được bảo đảm để chạy kể từ khi 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 họ cuối cùng sẽ bị hủy diệt

  • AsyncTask có thể được tự động chấm dứt, ngay cả khi 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 nó

  • phương thức AsyncTask chạy trên Giao diện người dùng, như onPostExecute, có thể được thực hiện khi Hoạt động mà nó đang đề 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.

Kết luận bạn không nên sử dụng các phương pháp được liên kết với UIThread của AsyncTask, lợi thế chính của nó !!! Hơn nữa, bạn chỉ nên làm công việc không quan trọng trên doInBackground. đã đọc chủ đề này để biết thêm những hiểu biết về vấn đề này:

Is AsyncTask really conceptually flawed or am I just missing something?

Để kết luận cố gắng để thích sử dụng IntentServices, HandlerThread hoặc ThreadPoolExecutor thay vì AsyncTask khi bất kỳ ở trên trích dẫn vấn đề ma là một mối quan tâm dành cho bạn. 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.

+0

+1, tôi đang tìm cách tiếp cận tốt nhất trong trường hợp của mình :) –

+0

Vâng, tôi đã dành rất nhiều thời gian để hối hận về việc sử dụng nhiều AsyncTask. Họ có vẻ tuyệt vời, nhưng ... rất nhiều vấn đề! –

+4

Tôi rất tiếc khi đăng bài mạnh mẽ chống lại điểm của bạn, nhưng tôi không thể để hiệu ứng phong cách kém của bạn trở thành ứng dụng android. Điểm một. Bạn KHÔNG nên có nhiều chuỗi chạy. Nếu bạn bắt gặp thì 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, 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 vô lý 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ý công việc của bạn, không được thô lỗ, là một kỹ năng mới. Bạn có thể giết nó khi bạn gọi onPause, hoặc bạn đúng cách tách ra và đính kèm cho phù hợp. – StarWind0

0

Đó là câu hỏi phỏng vấn tốt nhất được hỏi. AsyncTask - Chúng được sử dụng để loại bỏ chuỗi giao diện người dùng và thực hiện các tác vụ ở chế độ nền. Trình xử lý - Android dosent có cách giao tiếp trực tiếp giữa giao diện người dùng và chuỗi nền. Trình xử lý phải được sử dụng để gửi tin nhắn hoặc runnable thông qua hàng đợi tin nhắn.

Vì vậy AsyncTask được sử dụng khi thực hiện các tác vụ trong nền và Trình xử lý được sử dụng để liên lạc giữa giao diện người dùng và Chủ đề nền.

0

AsyncTask giả sử bạn sẽ làm điều gì đó trên chuỗi giao diện người dùng, sau khi hoàn thành một số thao tác nền. Ngoài ra, bạn chỉ có thể thực hiện nó một lần (sau này, trạng thái của nó là FINISHED và bạn sẽ nhận được một ngoại lệ 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ó 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.

Handler khô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ể chạy nhiều lần như bạn muốn. Bạn được tự do quyết định nên gắn nó vào chủ đề nào, nó liên kết với các trình xử lý khác như thế nào, có thể tạo ra chúng với HandlerThread. Vì vậy, nó linh hoạt hơn nhiều và thích hợp cho một số công việc lặp đi lặp lại.

Kiểm tra loại khác nhau của Handler ví dụ here.

0

doInBackground - về cơ bản không hoạt động trong chuỗi khác. onPostExecute - đăng kết quả trên chuỗi giao diện người dùng và gửi nội bộ thông báo tới bộ xử lý của chuỗi chính. Chủ đề giao diện người dùng chính đã có một looper và trình xử lý được liên kết với nó.

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 phải được cập nhật trên giao diện người dùng, nó sẽ được sử dụng xử lý chủ đề chính.

Các vấn đề liên quan