Câu trả lời được đưa ra bởi @Romain Guy là chính xác. Tuy nhiên, tôi muốn thêm phần bổ sung thông tin và cung cấp một con trỏ cho thư viện hoặc 2 có thể được sử dụng cho AsyncTask chạy lâu dài và thậm chí nhiều hơn nữa cho các asynctasks hướng mạng.
AsyncTasks đã được thiết kế để thực hiện mọi thứ trong nền. Và có, bạn có thể dừng nó bằng cách sử dụng cancel
phương pháp này. Khi bạn tải xuống nội dung từ Internet, tôi thực sự khuyên bạn nên quan tâm đến chuỗi của mình khi nó ở trạng thái chặn IO . Bạn nên tổ chức tải xuống của mình như sau:
public void download() {
while( inputStream.read(buffer) != -1 && !Thread.interrupted() ) {
}
}
Sử dụng Thread.interrupted
cờ sẽ giúp chuỗi của bạn thoát khỏi trạng thái io chặn đúng cách. Luồng của bạn sẽ phản hồi nhanh hơn với một lệnh gọi cancel
phương thức.
Lỗ hổng thiết kế AsyncTask
Nhưng nếu AsyncTask của bạn tồn tại quá lâu, thì bạn sẽ gặp phải 2 vấn đề khác nhau:
- Các hoạt động có mối liên hệ chặt chẽ với vòng đời hoạt động và bạn sẽ không nhận được kết quả của AsyncTask nếu hoạt động của bạn không hoạt động. Thật vậy, có, bạn có thể nhưng đó sẽ là con đường khó khăn.
- AsyncTask không được ghi chép đầy đủ. Việc triển khai và sử dụng một asynctask ngây thơ, mặc dù trực quan, có thể nhanh chóng dẫn đến rò rỉ bộ nhớ.
RoboSpice , thư viện mà tôi muốn giới thiệu, sử dụng một dịch vụ nền để thực hiện loại yêu cầu này. Nó đã được thiết kế cho các yêu cầu mạng. Nó cung cấp các tính năng bổ sung như lưu trữ tự động các kết quả của yêu cầu.
Đây là lý do tại sao AsyncTasks không tốt cho các tác vụ chạy lâu. Lý do sau đây là sự chuyển thể từ các đoạn trích của động cơ RoboSpice : ứng dụng giải thích tại sao việc sử dụng RoboSpice đang đáp ứng nhu cầu trên nền tảng Android.
Vòng đời của AsyncTask và Activity
AsyncTasks không tuân theo vòng đời của phiên bản Activity. Nếu bạn khởi động AsyncTask bên trong Hoạt động và bạn xoay thiết bị, Hoạt động sẽ bị hủy và một phiên bản mới sẽ được tạo. Nhưng AsyncTask sẽ không chết. Nó sẽ tiếp tục sống cho đến khi hoàn thành.
Và khi hoàn tất, AsyncTask sẽ không cập nhật giao diện người dùng của Hoạt động mới. Thật vậy, nó cập nhật phiên bản cũ của hoạt động không được hiển thị nữa. Điều này có thể dẫn đến Ngoại lệ của kiểu java.lang.IllegalArgumentException: Chế độ xem không được đính kèm với trình quản lý cửa sổ nếu bạn sử dụng, chẳng hạn, findViewById để truy xuất chế độ xem bên trong Hoạt động.
Sự cố rò rỉ bộ nhớ
Rất thuận tiện để tạo AsyncTasks làm lớp bên trong Hoạt động của bạn. Vì AsyncTask sẽ cần thao tác các khung nhìn của Activity khi nhiệm vụ đã hoàn thành hoặc đang diễn ra, việc sử dụng lớp bên trong của Activity có vẻ thuận tiện: các lớp bên trong có thể truy cập trực tiếp vào bất kỳ trường nào của lớp bên ngoài.
Tuy nhiên, nó có nghĩa là lớp bên trong sẽ giữ một tham chiếu vô hình trên cá thể lớp bên ngoài của nó: Activity.
Về lâu dài, điều này dẫn đến rò rỉ bộ nhớ: nếu AsyncTask tồn tại lâu, nó sẽ giữ cho hoạt động "tồn tại" trong khi Android muốn loại bỏ nó vì nó không thể hiển thị được nữa. Hoạt động không thể được thu thập rác và đó là cơ chế trung tâm để Android duy trì tài nguyên trên thiết bị.
Tiến độ nhiệm vụ của bạn sẽ bị mất
Bạn có thể sử dụng một số giải pháp thay thế để tạo một asynctask hoạt động lâu dài và quản lý vòng đời của nó tương ứng với vòng đời của hoạt động. Bạn có thể hủy AsyncTask trong phương pháp onStop của hoạt động của mình hoặc bạn có thể để tác vụ không đồng bộ của mình kết thúc và không làm mất tiến trình của nó và liên kết lại nó với phiên bản hoạt động tiếp theo của bạn .
Điều này là có thể và chúng tôi chỉ ra cách trong RobopSpice động lực, nhưng nó trở nên phức tạp và mã không thực sự chung chung. Hơn nữa, bạn vẫn sẽ mất tiến độ thực hiện nhiệm vụ của mình nếu người dùng rời khỏi hoạt động và quay lại. Vấn đề tương tự này cũng xuất hiện với Loaders, mặc dù nó sẽ đơn giản hơn tương đương với AsyncTask với cách giải quyết liên tục được đề cập ở trên.
Sử dụng dịch vụ Android
Tùy chọn tốt nhất là sử dụng một dịch vụ để thực hiện các tác vụ chạy nền lâu dài của bạn. Và đó chính xác là giải pháp do RoboSpice đề xuất. Một lần nữa, nó được thiết kế cho mạng nhưng có thể được mở rộng cho những thứ không liên quan đến mạng. Thư viện này có một số lượng lớn các tính năng .
Bạn thậm chí có thể có được ý tưởng về nó trong vòng chưa đầy 30 giây nhờ vào đồ họa thông tin .
Thực sự là một ý tưởng rất tồi khi sử dụng AsyncTasks cho các hoạt động chạy dài. Tuy nhiên, chúng phù hợp với những hoạt động ngắn hạn như cập nhật Chế độ xem sau 1 hoặc 2 giây.
Tôi khuyến khích bạn tải xuống ứng dụng RoboSpice Motivations , ứng dụng này thực sự giải thích chuyên sâu về vấn đề này và cung cấp các mẫu và minh họa về các cách khác nhau để thực hiện một số nội dung liên quan đến mạng.
Nếu bạn đang tìm kiếm một giải pháp thay thế cho RoboSpice cho các tác vụ không liên quan đến mạng (ví dụ như không có bộ nhớ đệm), bạn cũng có thể xem Tape .