Đối với bất kỳ ứng dụng nào
cũng đều phải chú ý đến hiệu năng thực hiện của ứng dụng. Với các
thao tác load hình ảnh, dữ liệu, đặc biệt khi có giao tiếp với
internet, không nên để các quá trình này chạy trong main thread.
Ví dụ:
public void onClick(View v){
downloadData(uri);
Log.i("exam", "Download data completed. Process the next command
lines");
showOnLayout();
}
Trong sự kiện onClick, ta cho hàm
downloadData chạy trong main thread, hàm Log.i() và hàm showOnLayout()
phải chờ cho đến khi hàm downloadData() chạy xong => lúc này bị
block UI Thread
·
2 nguyên tắc hàng đầu cần phải nhớ:
1.
Không block UIThread
2.
Không update view ngoài UI Thread (còn gọi
là main thread). Việc update view phải được thực hiện trong main thread.
Ví dụ:
public void onClick(View v){
new Thread(){
run(){
downloadData(uri);
}.start();
}
}
ð
Lúc này, việc downloadData() được thực
hiện trong Thread riêng, không gây block UI Thread.
Câu hỏi: trong trường
hợp muốn lấy dữ liệu load về vào trong UI Thread thì làm thế nào?
Ví dụ:
onClick{
new Thread(){
run(){
image
= downloadData(uri);
ImageView.setImageSource(image);
//=>
đụng vấn đề cập nhật view ngoài main thread.
}.start();
}
}
ð
Có 2
cách xử lý như sau:
Cách 1:
activity.runOnUIThread(new Runnable(){
run(){
ImageView.setImageResource(...);
}
});
Cách 2:
ImageView.post(new Runnable()){
run(){
ImageView.setImageResource(...);
}
}
ð
Lúc này nảy sinh vấn đề mới: thread quá
nhiều => khắc phục bằng cách dùng AsyncTask => UI Tread vẫn có
thể được thực hiện, data vẫn có thể download, cũng có thể cập nhật
view
Ví dụ:
class DownloadImage extends AsyncTask<Object1, Object2, Object3>{
}
Trong đó:
-
Object1:
dữ liệu cần thiết để chạy, ví dụ: uri dùng để download data
-
Object2:
tham số dưới background muốn bắn lên trong UI => thong báo về tình
trang download, phần tram download, có thể thực hiện ngay khi việc load
data dưới background chưa hoàn thành.
-
Object3:
dùng để cập nhật View khi công việc download hoàn thành.
Khi extends từ AsyncTask cần phải override các
phương thức sau đây:
-
Public
void onPreExcute(){
ð thực hiện trong UI Thread, gồm
các thao tác trước khi thực hiện công việc ở background. Vd: show thanh
progressBar
}
-
public
Object3 doInBackground(Object1){
public progress(Object2){}
ð Thực hiện trong Thread khác, lấy
dữ liệu đang download về, lấy thong tin tiến trình, hiển thị % download
ð Muốn thực hiện cập nhật View
khi dữ liệu download về chưa xong (download tới đâu, cập nhật View tới đó),
dùng onProgressUpdate()
}
-
Protected
void onPostExcute(Object3){
ð Thực hiện trong UI Thread, sau
khi hoàn thành tiến trình. Vd: đóng progressBar lại
}
-
Protected
onProgressUpdate(Object2){
ð Cập nhật UI dựa trên data đang
download dỡ dang về.
}
Cuối cùng, ta viết lại hàm ban đầu như sau:
public void onClick(View
v){
new DownloadImage().excute(Object1);
}
Bài
viết chỉ với mục đích lưu trữ. Cám ơn thầy Bùi Quốc Ánh đã giúp
đỡ em thực hiện bài viết này.
ghê gớm nhễ
Trả lờiXóa+1 đê
Trả lờiXóacho hỏi
Trả lờiXóaactivity.runOnUIThread(new Runnable(){
run(){
ImageView.setImageResource(...);
}
});
activity ở đây là đối tượng gì vậy
chào bạn, activity là đối tượng thuộc lớp Activity. Bạn có thể xem lại các phương thức của lớp Activity ở đây: http://developer.android.com/reference/android/app/Activity.html
Xóatuyệt
Trả lờiXóa