Cách sử dụng Asynctask cụ thể trong app
Chào cả nhà, mình là thành viên mới và đang tập tành cơ bản nhất về android studio. Mình đang làm một app và đang bị lỗi ANRs mà không biết phải xử lý thế nào nhờ mọi người giúp đỡ.
App của mình cụ thể như sau:
- Mình có một Gridview chứa nhiều ảnh (có chứa google banner ads)
- Khi bấm vào mỗi ảnh, một dialog sẽ hiện ra và chứa ảnh đó ở cỡ lớn (không chứa ads)
Nhưng khi chạy bị báo lỗi ANRs.
Mình có tìm hiểu là nên sử dụng Asynctask nhưng mình không biết sử dụng như thế nào. Async cho Gridview hay cho dialog?
1 CÂU TRẢ LỜI
Hi bạn. Để trả lời câu hỏi này, mình giải thích thêm một số khái niệm cơ bản có lẽ sẽ giúp ích cho bạn khi làm Android app sau này.
Android có 2 loại Thread:
- Main thread (UI thread): Thread group xử lý các tác vụ liên quan đến UI.
- Background thread (Worker thread) : Thread group xử lý các tác vụ khác, không liên quan đến UI.
Mặc định Android component như Activity
, Fragment
, Service
chạy trên main thread, và khi có quá nhiều long running task trên thread này, ARN error sẽ xuất hiện, indicate rằng app UI không phản hồi trong thời gian quá lâu, lúc này bạn không thể thao tác với UI hoặc UI lag rất nhiều. Đọc logcat, bạn sẽ thấy dòng info ... to much work on main thread, skip xxx frames
.
Để giải quyết vấn đề này, các tác vụ nặng, cần xử lý nhiều cần thiết phải bring out khỏi main thread. Các đơn giản nhất, bạn có các cách tham khảo sau:
1. Thread allocation
new Thread(() -> {
// Do stuff here
}).start();
Đoạn code trong lamda sẽ run ở background thread và bạn trigger callback khi done.
2. AsyncTask
new AsyncTask<String, Void, Boolean>(){
@Override
protected Boolean doInBackground(String... strings) {
// Running in background
// Do stuff here and return value
return null;
}
@Override
protected void onPreExecute() {
// Run on main thread, update UI or stuffs like that
super.onPreExecute();
}
}.execute();
3. ThreadPoolExecutor
ThreadPoolExecutor executor = new ThreadPoolExecutor(2, 5, 30, TimeUnit.SECONDS, new LinkedBlockingQueue<>(),
(ThreadFactory) Thread::new);
executor.execute(() -> {
// Do stuff here and trigger callback when done
})
Cách này sẽ giúp tối ưu thread sinh ra và manage nó tốt hơn cách 1 khi bạn allocate thread nhưng lost control khi nó đã thực hiện xong.