50

Tôi đang thiết kế một ứng dụng android mà sẽ cần phải làm theo các bước sau:cân nhắc thiết kế android: AsyncTask vs Service (IntentService?)

  1. dùng đẩy một nút hoặc chỉ để "dữ liệu đồng bộ".
  2. quy trình đồng bộ hóa sẽ sử dụng các dịch vụ web REST để di chuyển dữ liệu đến và từ máy chủ.
  3. dữ liệu sẽ được lưu trữ cục bộ trong cơ sở dữ liệu sqlite.
  4. quy trình đồng bộ hóa sẽ cung cấp cập nhật trạng thái/tin nhắn cho UI
  5. người dùng không được phép đi lang thang đến các phần khác của ứng dụng và thực hiện nhiều công việc hơn trong quá trình đồng bộ hóa.

Lần đầu tiên quá trình đồng bộ hóa chạy, có thể mất 10-20 phút. Sau khi đồng bộ hóa ban đầu, ít dữ liệu hơn sẽ được chuyển và lưu trữ và Tôi mong đợi quá trình mất từ ​​1-2 phút trở xuống.

Tôi đã đọc rất nhiều về số điện thoại AsyncTask và các ví dụ khác nhau về cách sử dụng Dịch vụ ... Nhưng tôi không hiểu đầy đủ các cân nhắc về thiết kế và thương mại khi chọn một thiết kế so với thiết kế kia. Tôi hiện đang có dự án demo của tôi stubbed ra bằng cách sử dụng một AsyncTask. Sau khi xem (hầu hết) Phát triển ứng dụng khách Android REST: http://code.google.com/events/io/2010/sessions/developing-RESTful-android-apps.html# Tôi bị nhầm lẫn với các mẫu thiết kế được mô tả ở đây cảm thấy quá phức tạp , có lẽ vì tôi chưa "nhận được nó".

Tôi đến từ nền ứng dụng java, mùa xuân, web và máy tính để bàn. Suy nghĩ và thiết kế về mặt thiết bị cầm tay khá mới mẻ đối với tôi. (Điều gì sẽ xảy ra khi bố cục màn hình bị thay đổi? Điều gì sẽ xảy ra khi điện thoại đổ chuông khi tôi đang chạy đồng bộ?) Quay lại 2 bước, nếu đồng bộ hóa ban đầu IS sẽ là quá trình chạy dài, có cách nào tốt hơn không tôi nghĩ về vấn đề-> giải pháp, trải nghiệm người dùng, kỳ vọng của người dùng về một ứng dụng đang chạy trên điện thoại?

Rất thích nghe từ một số nhà phát triển Android có kinh nghiệm hơn ngoài kia, những người đã vật lộn với những câu hỏi này.

+0

quy trình đồng bộ hóa sẽ mất bao lâu (thường)? – binnyb

+0

đồng bộ ban đầu có thể mất 10-20 phút b/c số lượng dữ liệu sẽ được kéo xuống. sau đó, quá trình này có thể mất 1-2 phút hoặc ít hơn. – tia

Trả lời

5

Với AsyncTask nếu người dùng chuyển đến Hoạt động khác, bạn không thể chuyển đối tượng đó sang Hoạt động khác để nó chết. Có những thủ thuật bạn có thể chơi khi nói người dùng quay màn hình hoặc một cái gì đó như thế, nhưng điều đó không mở rộng đến mục đích chung hủy diệt. AsyncTask có thể ngẫu nhiên chết.

Google Sync được chạy dưới dạng Dịch vụ dưới nền vì quá trình đồng bộ hóa có thể mất chút thời gian để hoàn thành. Bạn có thể cần phải đi theo con đường của họ và tạo dịch vụ đồng bộ hóa của riêng bạn mà bạn có thể liên lạc. Dưới đây là một vài suy nghĩ làm thế nào để thực hiện điều đó:

http://mylifewithandroid.blogspot.com/2008/01/about-binders.html

Bạn chắc chắn có thể giao tiếp giữa dịch vụ và hoạt động, nhưng nó khó khăn để làm điều đó đúng.

12

Có nhiều cân nhắc mà bạn phải cân nhắc để quyết định cách tốt nhất để tiếp cận tình huống của bạn. Nghe có vẻ như bạn cần so sánh tốt giữa hai cách tiếp cận ... Vì vậy, đây là danh sách các điểm tương đồng, và sự khác biệt và cân nhắc bổ sung phải được tính đến khi làm việc trên thiết bị cầm tay.

Dịch vụ là một phần của Ứng dụng của bạn không có giao diện người dùng. Nó có thể được gọi bằng một UI (Hoạt động) để bắt đầu, hoặc có thể được bắt đầu bởi bất kỳ thành phần nào khác của Ứng dụng của bạn.Khi phát triển, bạn có quyền tự do đặt nó trên một luồng khác hoặc thậm chí chạy nó trong một Tác vụ hoặc Quy trình khác. Điều này cho phép bạn tách biệt nó khỏi giao diện người dùng của mình. Ngoài ra, bạn có thể bắt đầu Dịch vụ để chạy độc lập (startService) hoặc liên kết hoạt động của bạn với nó (bindService) tùy thuộc vào nhu cầu của bạn. Bằng cách sử dụng Trình xử lý tùy chỉnh, bạn có thể đặt các cuộc gọi lại để cập nhật giao diện người dùng với tiến độ của mình. Dịch vụ không nhất thiết kết thúc nếu Người dùng thay đổi Hoạt động nhưng có thể kết thúc vào bất kỳ lúc nào bởi HĐH.

AsyncTask luôn được khởi tạo từ chuỗi giao diện người dùng. Nó chỉ cho phép gọi lại cụ thể, nhưng đơn giản hóa quá trình đa luồng cho các mục đích giao dịch tương đối ngắn (so với các dịch vụ luồng riêng biệt chuyên biệt) vốn đã gắn liền với các hành động được thực hiện bởi một Hoạt động. Bất cứ khi nào Người dùng thay đổi Hoạt động, AsyncTask được đặt vào "tạm dừng" và thậm chí có thể chết vì không có chuỗi giao diện người dùng nào cho Hoạt động của bạn nữa. Điều quan trọng nhất là nếu ứng dụng sẽ mất 10-20 phút lần đầu tiên, tôi sẽ giả định rằng người dùng sẽ thay đổi tác vụ tạm thời hoặc đặt điện thoại xuống cho đến khi nó hoàn thành (trong đó có thể gây ra tất cả các biến chứng tương tự nếu điện thoại ngủ). Với điều này xem xét, một dịch vụ luồng ràng buộc với hoạt động của bạn có thể là sự lựa chọn tốt nhất của bạn. Để bảo vệ giao diện người dùng của bạn, tôi sẽ tạo Hộp thoại tiến trình cho Hoạt động của bạn để nhận các cuộc gọi lại tiến độ của bạn. Điều này giới hạn đầu vào của người dùng trong ứng dụng CỦA BẠN và cho phép dịch vụ của bạn tiếp tục theo cách cần thiết. Sau đó ghi đè lên Activity onResume để kiểm tra trạng thái của Dịch vụ của bạn và nếu nó đang chạy. Sau đó, bạn có thể đặt lại Hộp thoại ngay lập tức.

Vì đây là phương pháp ưa thích của tôi, tôi cũng sẽ tính đến việc hệ điều hành có thể giết ứng dụng bất cứ lúc nào. Vì vậy, hãy chắc chắn để có một số cách để phát hiện một đồng bộ hóa không đầy đủ hoặc một phần. Sau đó, bạn có thể tiếp tục tự động khi Hoạt động hoặc Dịch vụ của bạn khởi động lại.

44

Theo tôi, đây là phần khó khăn/khó khăn nhất của sự phát triển Android chính thống/trung bình. Ví dụ trên BlackBerry, đây là IN TIMES dễ dàng hơn.

Chắc chắn bạn cần sử dụng Service.

AsyncTask không phù hợp, bởi vì nó là chặt chẽ "buộc" vào Activity của bạn thông qua một tay cầm Context (nếu không bạn sẽ không thể cập nhật giao diện người dùng của Activity từ AsyncTask của bạn). Tuy nhiên, Activity có thể bị hệ điều hành giết sau khi Activity chạy ẩn. Một lý do ví dụ về việc chuyển sang nền có thể là cuộc gọi đến - người dùng chuyển sang ứng dụng Điện thoại để Activity của bạn trở nên vô hình. Trong trường hợp này (tùy thuộc vào trạng thái RAM hiện tại) Hệ điều hành có thể quyết định giết một trong các hoạt động nền (ẩn với người dùng).

Một số nhà phát triển giải quyết vấn đề này bằng cách sắp xếp công cụ tĩnh để có hành động lâu dài bên trong. Một số đề xuất sử dụng ví dụ Application. Điều này là do công cụ tĩnh và Application tồn tại trong khi toàn bộ quá trình ứng dụng tồn tại. Tuy nhiên đó là cách giải quyết không chính xác. Các quy trình trong Android cũng có thể bị hủy khi hệ điều hành quyết định đã đến lúc. Hệ điều hành Android có những cân nhắc riêng về những gì nó có thể giết chết và theo thứ tự nào. Tất cả các quá trình được chia thành 5 cấp độ "khả năng giết người". Here is the doc nơi các cấp đó được chỉ định. Thật thú vị khi đọc có:

Bởi vì một quá trình chạy một dịch vụ là xếp hạng cao hơn một với các hoạt động nền , một hoạt động mà khởi một hoạt động lâu dài có thể làm tốt để bắt đầu một dịch vụ cho điều đó hoạt động, thay vì chỉ sinh ra một sợi - đặc biệt nếu hoạt động sẽ có khả năng tồn tại lâu hơn hoạt động.Ví dụ trong số này đang phát nhạc ở nền và tải ảnh được máy ảnh chụp lên trang web. Sử dụng dịch vụ đảm bảo rằng hoạt động sẽ có ít nhất "ưu tiên dịch vụ ", bất kể những gì xảy ra với hoạt động.

bạn Activity nơi người dùng bắt đầu một hành động dài chạy sẽ hiển thị một ProgressDialog để đảm bảo người dùng không làm bất cứ điều gì khác trong khi hành động đang chạy. Hướng dẫn là here.

Ngoài ra, bạn có thể muốn sử dụng NotificationManager để thông báo cho người dùng về việc hoàn thành hành động dài hạn của bạn (hoặc lỗi) nếu Activity của bạn hiện không hiển thị. Đây là số NotificationManager info để bắt đầu.

+10

Chỉ cần quên nói 'IntentService' là một lựa chọn thực sự tốt đẹp. –

+1

Không bao giờ ít hơn, nó là giá trị mensionning rằng thông tin liên lạc từ hoạt động-to-dịch vụ là một chút khôn lanh. Việc tách giao diện người dùng và các tính năng mạng khá sâu và đòi hỏi một số nỗ lực mã hóa vì các giá trị sẽ phải được chuyển qua việc tuần tự hóa hoặc chuyển dịch hoặc thông qua AIDL. http://stackoverflow.com/questions/2463175/how-to-have-android-service-communicate-with-activity – Snicolas

+0

Xin chào, @ Arhimed tôi có một câu hỏi giống như vậy? [ở đây là] (http://stackoverflow.com/questions/14760507/execute-long-running-operations-on-the-service), bạn có thể cho tôi lời khuyên không. cảm ơn. – AlexSanchez

3

Lựa chọn chủ yếu phụ thuộc vào thiết kế ứng dụng. Vì cả AsyncTask và IntentService đều là nền tảng của họ, những gì bạn có thể muốn từ ứng dụng (trải nghiệm người dùng) quan trọng hơn và sau đó chọn một hoặc cả hai. Một số kịch bản được đề cập dưới đây (chủ yếu là những gì tôi đã trải qua trong khi các ứng dụng đang phát triển)

  • Giả sử các ứng dụng có nguồn cấp dữ liệu trang - nơi có hơn một cuộc gọi api được thực hiện để làm cho trang chỉnh tề (/ getFriends,/getDates,/getPictures vv) bạn có thể làm cong tất cả các cuộc gọi api như vậy đến một AsyncTask đơn lẻ với trình thực thi đa luồng và chuỗi thực thi không quan trọng. Ngược lại với IntentService chạy tất cả các cuộc gọi theo thứ tự trong một chuỗi công nhân đơn lẻ. Đối với thiết bị cao cấp có nhiều lõi, cuộc gọi từ AsyncTask hiệu quả hơn. Và nếu bạn khởi động AsyncTask trên giao diện người dùng, thì cập nhật IU là một mẩu bánh (đọc mã đĩa ít lò hơi hơn). Và ngay cả khi người dùng rời khỏi trang, với việc sử dụng thông minh không giữ cho ngữ cảnh thì ứng dụng không bị lỗi.

  • Giả sử bạn đang cố gắng viết ứng dụng không cần người dùng xem trên chế độ xem/hoạt động/phân đoạn và tổng thời gian thực hiện để hiển thị nội dung nào đó không phải là nhiệm vụ quan trọng (giả sử dịch vụ đồng bộ hóa hoặc thông báo/cảnh báo người dùng) thì IntentService là một lựa chọn tốt hơn. (Không có rắc rối để bắt đầu AsyncTask trên thread UI do đó bạn không cần phải viết một Handler để buộc thay đổi nào trên giao diện người dùng vv vv và ít mã tấm nồi hơi)

Từ kinh nghiệm của tôi - viết ứng dụng nhỏ cho cả hai và so sánh ưu và khuyết điểm để có ý tưởng tốt hơn. (ps tôi khuyên bạn nên xem xét ứng dụng iosched từ google để có ý tưởng tốt hơn - họ sử dụng cả Asynctask và IntentService)

+0

Câu trả lời hay. Asynctask là dễ dàng, đa nhiệm. IntentService là một nhiệm vụ khó khăn. Asynctask có điểm mạnh của nó, và nên được sử dụng để thực hiện nhất định. –

2

Tôi có xu hướng thích combo IntentService + BroadcastReceiver hơn vì chúng cung cấp cho bạn mức độ thực sự mạnh mẽ kiểm soát

Bạn chắc chắn phải đảm bảo giao diện người dùng đang chạy nếu bạn đang cập nhật nội dung nào đó trên màn hình. Sự cố ASyncTask đã được báo cáo là một trong những nguyên nhân hàng đầu gây ra sự cố Android. Điều này có thể tránh được bằng cách giữ một số loại biến "activityIsAlive" và bỏ qua hoặc trì hoãn cập nhật giao diện người dùng nếu hoạt động đó đã chết.

Kết hợp IntentService + BroadcastReceiver có khả năng chống va chạm ít hơn vì hầu hết các hướng dẫn đều cho bạn biết tắt BroadcastReceiver onPause hoặc onStop. Nếu bạn không làm điều này, một lần nữa bạn sẽ phải tắt cập nhật giao diện người dùng. Có một lệnh runOnUiThread ở đâu đó sẽ giúp bạn cập nhật giao diện người dùng.

Kết hợp IntentService + BroadcastReceiver cũng có thể mở rộng hơn.Bạn có thể tạo các chức năng và mở rộng BroadcastReceiver để thực hiện một giải pháp xử lý REST thanh lịch hơn. Tuy nhiên, nó yêu cầu hệ thống ống nước nhiều hơn so với ASyncTask

Nếu bạn trì hoãn cập nhật giao diện người dùng, bạn có thể cố định nó trên OnWindowFocusChangedListener. Khi hàm đó nhận được true, nó có nghĩa là giao diện người dùng còn sống.

tldr; Đảm bảo Hoạt động và/hoặc Phân đoạn còn hoạt động trước khi cập nhật giao diện người dùng nếu bạn đang chạy một cái gì đó ở chế độ nền

2015 Edit: hãy kiểm tra Trình tải là tốt. Hơi khó nắm bắt hơn vì có rất nhiều điều xảy ra đằng sau hậu trường

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