Khi sử dụng một ứng dụng trên Android, đôi khi bạn sẽ gặp phải tình trạng “Application Not Responding”. Phần lớn người dùng nghĩ rằng đây là tình trạng app bị treo, đứng máy hay lag. Tuy nhiên, vẫn còn một nguyên nhân khác dẫn đến tình trạng này. Đó là do UI Thread. Đối với nguyên nhân này, ta sẽ có giải pháp xử lý là AsyncTask. Vậy, AsyncTask Android là gì?
Tìm hiểu về AsyncTask Android
Hiện tượng “Application Not Responding” là gì?
Trong hệ điều hành Android, mỗi ứng dụng sẽ được hệ điều hành cung cấp cho một process và trên đó có một thread mặc định của ứng dụng. Android xử lý tất cả các tác vụ, tiến trình trên 1 thread duy nhất được gọi là Main UI thread. Main UI thread chỉ làm một việc trong sự kiện/task duy nhất trong tại một thời điểm.
Một task tốn nhiều thời gian trên Main UI thread sẽ dẫn đến tình trạng Android sẽ nhảy ra một thông báo có tên là: Application Not Responding (hay thường biết đến với cái tên ARN).
Thông thường, những tác vụ hao tốn nhiều tài nguyên như: giải nén file hoặc tải file từ Internet,… những tác vụ này cần phải thác khỏi Main UI thread. Nói cách khác, ta sẽ cần phải tạo ra xử lý đa nhiệm. Để thực hiện xử lý đa nhiệm ta có một số công cụ do Android cấp sẵn để dùng như:
- Sử dụng Thread
- Sử dụng Loader trong Android
- Sử dụng IntentService
- Hoặc dùng đến AsyncTask trong Android.
AsyncTask Android là gì?
Về lý thuyết, AsyncTask Android là một abstract Android class giúp Android trở nên “đa nhiệm” hơn khi xử lý main UI thread một cách hiệu quả. Bạn có thể sử dụng AsyncTask Android trong Android để thực hiện các tác vụ dài mà không làm ảnh hưởng đến main UI thread.
AsyncTask xuất hiện từ phiên bản API Level 3 trong Android, với mục đích đưa ra một tiêu chuẩn làm việc với main UI thread dễ dàng hơn.
AsyncTask được thiết kế như một class trợ giúp cho Thread và Handler, được sử dụng trong các hoạt động ngắn khoảng vài giây. Nếu bạn muốn tạo luồng dài hơi hơn, bạn nên sử dụng các class do java.util.concurrent cung cấp như: Executor, ThreadPoolExecutor hay FutureTask.
Trong bài viết sẽ giữ nguyên nhiều từ tiếng Anh như:
- Class: lớp
- Process: được sinh ra khi Android chạy và các ứng dụng trong Android đều được cấp 1 Process để thực thi.
- Thread: là một thực thể trong Process và là đối tượng lên kế hoạch thực thi.
- Handler: là một liên kết/ trao đổi được sinh ra trong quá trình các Thread trao đổi với nhau hoặc Thread sinh ra Handler.
- Abstract: trừu tượng
- Task: tác vụ
- Event: sự kiện
- Background: nền, trong bài sẽ ngầm hiểu là: chạy tác vụ dưới nền
Khi nào nên sử dụng AsyncTask Android
Thật sự, những thứ liên quan đến Abstract rất khó hiểu. Vì thế, Tino Group sẽ giải thích về AsyncTask Android là gì cùng trường hợp sử dụng AsyncTask trong Android nhé!
Ví dụ, bạn đang tải một file nhạc MP3 về thiết bị Android. Quá trình này diễn ra rất đơn giản trong mắt người dùng nhưng dưới nền, Android lại hoạt động rất phức tạp. Bạn có thể theo dõi sơ đồ sau để thấy quá trình tải 1 file MP3 là không hề đơn giản.
Điều này dẫn đến hệ lụy, khi chờ “hết thanh xuân” để máy chủ gửi file MP3 về, ứng dụng của bạn sẽ bị treo và hiện lên thông báo “Application Not Responding” vì lúc này main Thread vẫn đang chờ cho task tải MP3 hoàn tất.
Nếu điều này diễn ra thường xuyên, bản thân bạn có còn muốn tải nhạc về máy để nghe nữa hay không? Dĩ nhiên là “không” rồi đúng không nào?
Vì thế, Android cung cấp cho bạn một giải pháp chuyên dụng là class AsyncTask để tạo thêm một Thread mới và thực hiện task trên Thread đó giúp app không bị treo => người dùng không ảnh hưởng => người dùng hạnh phúc => bạn không “rate” 1 sao cho ứng dụng hoặc người dùng không “rate” 1 sao cho ứng dụng của bạn.
Một câu hỏi tiếp theo được đặt ra là: làm thế nào để triển khai AsyncTask trong Android?
Làm thế nào để triển khai AsyncTask trong Android?
4 bước triển khai AsyncTask trong Android
Khi AsyncTask thực thi, task sẽ trải qua 4 bước như sau:
- Bước 1 onPreExecute()
- Bước 2 doInBackground()
- Bước 3 onProgressUpdate()
- Bước 4 onPostExecute()
Chúng ta cùng nhau tìm hiểu chi tiết trong từng bước thông qua ví dụ tải file nhé! Trước tiên, bạn hãy tham khảo đoạn code mẫu dưới đây:
Bước 1: onPreExecute()
onPreExecute() sẽ được gọi trên UI thread khi task bắt đầu. Đây là bước cơ bản để bắt đầu quá trình chuẩn bị thực hiện một task. Ví dụ cụ thể nhất là sử dụng để tạo ra một thanh thông báo cho người dùng về % dữ liệu đã tải về.
Bước 2: doInBackground()
doInBackground() sẽ thực hiện nối tiếp dưới background với onPreExecute() ngay khi bước này hoàn tất. Vì doInBackground() hoạt động trên một Thread riêng với UI Thread. Do đó, bạn sẽ không thể và không được phép cập nhật giao diện tính toán quá trình ở đây.
Nếu bạn muốn thực hiện bạn sẽ cần phải sử dụng một hàm khác để hiển thị. Như trong ví dụ, hàm publishProgress(Progress…) sẽ là hàm được sử dụng để hiển thị % data đã tải về thiết bị.
Bước 3: onProgressUpdate()
onProgressUpdate() sẽ thực hiện nối tiếp theo publishProgress(Progress…) trên UI Thread. Thời gian thực hiện bước này là không xác định.
Phương thức này được sử dụng để hiển thị bất cứ hình dạng nào trong giao diện người dùng khi dưới nền vẫn đang thực hiện tính toán, ví dụ như bạn có thể tạo hiệu ứng cho thanh hiển thị % tải về hoặc hiển thị nhật ký tải về (giống như đoạn tải về trong IDM) bằng các văn bản.
Bước 4: onPostExecute()
onPostExecute() sẽ được gọi khi công việc tính toán của doInBackground() đã hoàn tất và kết thúc. Kết quả tính toán sẽ hiển thị dưới dạng một tham số và trả lên giao diện của người dùng.
Ngoài ra, bạn có thể sử dụng cancel(boolean) để tạm dừng tại một thời điểm bất kỳ khi AsyncTask đang thực hiện công việc, mà không cần phải chờ AsyncTask hoàn tất toàn bộ công việc.
Đến đây, Tino Group đã hoàn tất việc giải đáp AsyncTask Android là gì cũng như giải thích 4 bước triển khai AsyncTask trong Android bằng ví dụ trực quan và dễ hiểu nhất có thể. Nếu bạn vẫn chưa hiểu, chuyện này vẫn bình thường khi làm việc với các Abstract. Ngoài ra, bạn có thể tham khảo tài liệu chính thức của Google về AsyncTask Android tại đây.
Cuối cùng, Tino Group xin chúc bạn sẽ có những gặt hái thành công lớn trong tương lai với sự nghiệp lập trình Android bạn đang theo đuổi!
Bài viết có tham khảo từ nhiều nguồn: vntalking, Developer Android, open planning,…
Những câu hỏi thường gặp về AsyncTask Android
Vì sao một số code AsyncTask không hoạt động trên Android 11 trở lên?
Theo những công bố mới nhất và tài liệu xác thực từ chính Android, tính đến thời điểm hiện tại có 2 field bị chặn hoặc không chấp nhận sử dụng ở Android 11 (Android cấp 30) bao gồm:
- SERIAL_EXECUTOR, được thêm từ Android cấp 11
- THREAD_POOL_EXECUTOR, được thêm từ Android cấp 11
Android API Level là gì?
Android cấp x, hay còn được gọi là Android API Level, là một giá trị số nguyên định danh phiên bản framework API được cung cấp bởi phiên bản của nền tảng Android.
Nếu bạn muốn biết thêm về cấp Android hay Android API Level, tài liệu chính thức của Google về <uses-sdk> sẽ giải đáp rất nhiều thắc mắc của bạn.
Vì sao có nhiều Fields, Public methods lại không được các phiên bản Android mới hỗ trợ?
Có thể nói việc các phiên bản Android mới không hỗ trợ không phải vì không được hỗ trợ. Nguyên nhân chính của việc các Fields, Public methods lại không được các phiên bản Android mới hỗ trợ là bị Android cắt bớt nhằm gia tăng trải nghiệm của người dùng.
Ví dụ: SERIAL_EXECUTOR và THREAD_POOL_EXECUTOR sẽ tạo ra một nhóm luồng ưu tiên duy nhất khiến các tác vụ khác bị ảnh hưởng => không tối ưu tác vụ, khiến người dùng phải chờ đợi làm giảm trải nghiệm của người dùng.