Xử lý bất đồng bộ trong lập trình Android cơ bản
Khóa học lập trình Android cơ bản

Danh sách bài học
Xử lý bất đồng bộ trong lập trình Android cơ bản
Nội dung bài viết Học nhanh
Dẫn nhập
Ở các bài học trước, chúng ta đã cùng nhau tìm hiểu về ANIMATION & CÁC HIỆU ỨNG ĐƠN GIẢN TRONG ANDROID. Tiếp theo ở bài học này chúng ta sẽ đề cập đến một khía cạnh quan trọng khác trong lập trình Android, đó là xử lý bất đồng bộ. Bài tiếp sau nữa cũng sẽ liên quan nên các bạn hãy chú ý kỹ nhé!
Nội dung
Để đọc hiểu bài này tốt nhất các bạn nên có kiến thức cơ bản về các phần:
- CẤU TRÚC CƠ BẢN MỘT CHƯƠNG TRÌNH ANDROID
- Biết trước về Thread và Handler (2 khái niệm cơ bản trong Java concurrency).
- Bình tĩnh, tự tin.
Trong bài học này, chúng ta sẽ cùng tìm hiểu các vấn đề:
- ANR.
- Làm quen với lỗi thao tác mạng phổ biến.
- Làm ví dụ xử lý download thông tin trên mạng và hiển thị về máy.
ANR
ANR là viết tắt của Application Not Responding (Ứng dụng không phản hồi).
Nếu đã từng sử dụng máy Android chắc hẳn bạn cũng đã ít nhất một lần gặp phải cái gì đó tương tự thế này:
Nguyên nhân có thể do rất nhiều: Lỗi null, các exception được bắn ra nhưng không xử lý,… Hoặc là:
- Không có phản hồi cho các sự kiện xuất / nhập thông tin (ghi dữ liệu vào bộ nhớ, nhập văn bản,…). Nói đơn giản là TREO máy.
- Broadcast Receiver không hoàn thành trong vòng 10 giây.
- Với các máy Androdi 3.1 về trước: Thao tác liên quan đến mạng quá 5 giây. Sau phiên bản 3.1 thì Google đã cấm tiệt thao tác mạng trên Main Thread.
Về cơ bản là như vậy. Tuy nhiên, hẳn các bạn sẽ tự hỏi…
Main Thread và Worker Thread là gì?
Mình đã giới thiệu ở bài đầu tiên, Android là hệ điều hành đa tiến trình, đa luồng. Các ứng dụng Android cũng có thể sử dụng được nhiều thread (luồng) tài nguyên hệ thống.
Tuy nhiên các thành phần liên quan đến giao diện người dùng đều được nhét chung vào một thread chính, gọi là UI Thread (hay Main Thread).
Các thao tác xử lý nặng hầu hết đều bị cấm thực thi trên Main Thread do sẽ gây ra trải nghiệm xấu cho người dùng (bấm nút mãi không lên, chạy mãi cứ treo là hỏng rồi, người ta sẽ xóa app ngay). Do đó chúng ta cần đưa các tác vụ này vào một Thread khác, gọi là Worker Thread.
Và sau đó là cập nhật vào Main Thread. Cách làm này được gọi là thao tác xử lý bất đồng bộ (Asynchronous).
Trăm nghe không bằng một thấy, chúng ta sẽ làm thử ví dụ nho nhỏ. Là download thông tin dạng String từ một site bất kỳ, sau đó in ra màn hình Android, từ trên Main Thread lẫn Worker Thread xem chúng thực sự ra sao nhé.
ANR với thao tác mạng trên Main Thread.
Bước 1: Như mọi khi, chúng ta tạo một project mới với tên là AsyncExample với API là 13 và loại Activity là Empty Activity.
Bước 2: Để cho đơn giản, dữ liệu của chúng ta sẽ lấy từ trang icanhazip.com. Vào trang này các bạn sẽ thấy địa chỉ IP của mình hiện ra. Và chúng ta sẽ đặt một TextView cho hiển thị địa chỉ này lên Activity.
Activity_main.xml
Bước 3: Trong MainActivity.java, chúng ta sẽ viết một hàm đơn giản, download thông tin từ icanhazip về và đổ vào TextView, tên hàm là testNetwork():
MainActivity.java
Nhớ đặt Permission Internet trong file AndroidManifest.xml
Và tất nhiên là chương trình sẽ bị crash rồi, do hàm testNetwork được gọi ngay trong UI Thread mà:
Và khi nhìn vào log, bạn sẽ thấy NetworkOnMainThreadException:
Vậy phải làm sao đây?
AsyncTask
Nói về xử lý bất đồng bộ thì quả thực không đơn giản. Mình cũng thừa nhận là mình cực kỳ gà ở khoản này. Nhưng may mắn thay là Android có một cơ chế giúp đơn giản hóa quá trình xử lý bất đồng bộ hiệu quả, phù hợp với ứng dụng nhỏ.
Đó chính là AsyncTask.
Bước 1: Chúng ta tạo một class mới, extends từ lớp AsyncTask, tạm gọi là AsyncTaskNetwork và nó có dạng ban đầu như sau:
AsyncTaskNetwork.java
Vào menu Code > Override Methods để tạo các method cần thiết. Thật ra chỉ cần doInBackground nhưng theo mình, nên tạo method theo thứ tự sau: onPreExecute, doInBackground và onPostExecute:
Và nó có dạng như này:
AsyncTaskNetwork.java
Phần này tương đối khó hiểu. Các bạn lưu ý nhé: Chúng ta có 3 phần:
- onPreExecute: Tác vụ này vẫn chạy ở UI Thread, nó sẽ chạy trước khi bắt đầu tác vụ bất kỳ nào đó trong doInBackground. Thích hợp nhất là đặt ở đây một ProgressDialog (một thông báo nhỏ quay quay) để cho người dùng biết là đang có tác vụ xử lý.
- doInBackground: Đây chính là cái chúng ta cần. Các thao tác về mạng sẽ được đặt vô đây. doInBackground là task chạy trên Worker Thread.
- onPostExecute: Tác vụ này chạy ở UI Thread, chúng ta sẽ cho dừng ProgressDialog ở đây, đồng thời lấy dữ liệu từ doInBackground về sau khi xử lý.
Các bạn có để ý đến các chỗ bôi màu chữ không? Đó chính là:
- String: Đây là kiểu dữ liệu được truyền vào doInBackground.
- Void: Đây là kiểu dữ liệu mà ta truyền vào một hàm đặc biệt có tên publishProgress(). Hàm này có sẵn trong lớp AsyncTask nhưng chúng ta không sử dụng đến. Nó dùng để cập nhật xem tác vụ đã chạy đến đâu rồi.
- Boolean: Kiểu dữ liệu trả về sau khi hoàn thành AsyncTask. Ở đây mình đặt Boolean để thông báo: Tác vụ xử lý mạng có thành công hay không.
Và chúng ta có class AsyncTask hoàn chỉnh như thế này, để ý kỹ chỗ string[0]:
Quay lại MainActivity. Cách áp dụng AsyncTask rất đơn giản như sau, chú ý phần tham số của execute:
Đó, 2 phần tham số mình đã đánh dấu tô đậm màu vàng. Cái địa chỉ kia chính là tham số thứ nhất trong mảng string… của AsyncTask (phần tử 0). Bạn có thể truyền vào bao nhiêu tham số cũng được, nhưng phải cùng kiểu và xử lý chu đáo.
Chạy app, và chúng ta có được:
Lưu ý là IP trên là của mình, của các bạn có thể khác.
Kết luận
Qua bài này chúng ta đã nắm được AsyncTask là gì, cơ chế bắt buộc xử lý tác vụ mạng trên Worker Thread của Android.
Chúng ta sẽ tìm hiểu sâu hơn về thao tác với mạng bằng Moshi và thư viện OkHttp qua bài JSON & WEB API TRONG LẬP TRINH ANDROID
Cảm ơn các bạn đã theo dõi bài viết. Hãy để lại bình luận hoặc góp ý của mình để phát triển bài viết tốt hơn. Đừng quên “Luyện tập – Thử thách – Không ngại khó”.
Tải xuống
Tài liệu
Nhằm phục vụ mục đích học tập Offline của cộng đồng, Kteam hỗ trợ tính năng lưu trữ nội dung bài học Xử lý bất đồng bộ trong lập trình Android cơ bản dưới dạng file PDF trong link bên dưới.
Ngoài ra, bạn cũng có thể tìm thấy các tài liệu được đóng góp từ cộng đồng ở mục TÀI LIỆU trên thư viện Howkteam.com
Đừng quên like và share để ủng hộ Kteam và tác giả nhé!

Thảo luận
Nếu bạn có bất kỳ khó khăn hay thắc mắc gì về khóa học, đừng ngần ngại đặt câu hỏi trong phần bên dưới hoặc trong mục HỎI & ĐÁP trên thư viện Howkteam.com để nhận được sự hỗ trợ từ cộng đồng.
Tác giả/Dịch giả
Khóa học
Khóa học lập trình Android cơ bản
Serial tutorial hướng dẫn lập trình Android cơ bản
anh ơi cho em hỏi, em có thể viết hàm getResult từ Api trong doInBackground được không anh?
Lúc đầu Admin tạo class là
sau đó copy code vào lại là
làm em hoang mang quá xem đi xem lại mới biết khác nhau chỗ đó bảo không hiểu tại sao code mình lại khác code Admin