Post by Admin on Apr 30, 2017 16:02:32 GMT 7
AsyncTask, ProgressDialog
Đôi khi chúng ta phải làm việc với 1 lượng dữ liệu khổng lồ, hoặc chúng ta cần phải chờ đợi 1 vấn đề gì đó cần liên quan đến thời gian. Tất nhiên mạng internet thường được nhắc tới trong vấn đề này, khi chúng ta kết nối đến 1 trang web, tải file,… và phân tích 1 file có dung lượng lớn, chúng ta phải chờ cho chương trình thực hiện phân tích dữ liệu xong mới cho hiện thị lên màn hình. Do đó chúng ta dùng AsyncTask để làm việc đó, đồng thời để đông cứng màn hình, và thao tác người dùng, ta dùng thêm 1 hộp thoại mà ngăn người dùng phản ứng với ứng dụng cũng là một điều cần thiết. Ví dụ như sau:
Bạn thấy đó, AsyncTask cần gán 3 kiểu giá trị thực hiện, bao gồm <kiểu tham số đầu vào, kiểu giá trị dùng cho cập nhật công việc, kiểu kết quả trả về>, trên ví dụ trên tôi dùng <String, Integer, Void> có ý nghĩa như sau.
Khi bạn tạo 1 task, và sau đó dùng lệnh .execute(String…) thì tham số được truyền vào String này, mặc định nó có thể là 1 chuỗi, hoặc là 1 array, và khi đó, trong class task, hàm .onPreExecute được thực thi trước, một hộp thoại hiện ra với lệnh .show(), sau đó hàm .doInBackground(String… str) được thực thi, nó nhận tham số như là 1 array, do đó bạn cần chọn ra 1 vị trí của array này để lấy tham số thực hiện.
Trong quá trình thực hiện .doInBackground, bạn có thể dùng hoặc không hàm .publishProgress(kiểu tham số update), ở đây tôi chọn là kiểu Integer tương đương int, cho nên tôi truyền biến i vào cho nó, khi đó 1 hàm khác được thực thi ngay, đó là hàm .onProgressUpdate(Integer… i), ở đây nó cũng nhận tham số như là 1 array, bất kể bạn đưa vào 1 hay 2 giá trị i, do đó cũng phải lấy ra 1 giá trị để cập nhật lên MainActivity.
Cuối cùng, khi đã thực hiện xong hàm .doInBackgroud, nhanh chóng hàm .onPostExecute(kiểu giá trị trả về) được thực hiện, lúc đó ta dọn dẹp những thứ ta cần thiết, và tôi cho hộp thoại biến mất qua hàm .dismiss().
Đôi khi chúng ta phải làm việc với 1 lượng dữ liệu khổng lồ, hoặc chúng ta cần phải chờ đợi 1 vấn đề gì đó cần liên quan đến thời gian. Tất nhiên mạng internet thường được nhắc tới trong vấn đề này, khi chúng ta kết nối đến 1 trang web, tải file,… và phân tích 1 file có dung lượng lớn, chúng ta phải chờ cho chương trình thực hiện phân tích dữ liệu xong mới cho hiện thị lên màn hình. Do đó chúng ta dùng AsyncTask để làm việc đó, đồng thời để đông cứng màn hình, và thao tác người dùng, ta dùng thêm 1 hộp thoại mà ngăn người dùng phản ứng với ứng dụng cũng là một điều cần thiết. Ví dụ như sau:
package com.holyeyed.ctrtask;
import android.app.Activity;
import android.app.ProgressDialog;
import android.os.AsyncTask;
import android.os.Bundle;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.LinearLayout;
public class MainActivity extends Activity implements OnClickListener {
// tạo một hộp thoại cảnh báo khi đang quá trình thực hiện
ProgressDialog pd;
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
LinearLayout ll = new LinearLayout(this);
Button bt = new Button(this);
bt.setText("show dialog");
bt.setOnClickListener(this);
ll.addView(bt);
//chúng ta phải tạo lập hộp thông báo trước, không thiết lập bên class AsyncTask
pd = new ProgressDialog(this);
// lập tiêu đề
pd.setTitle("xin chờ");
// không cho người dùng hủy bỏ hộp thoại giữa chừng
pd.setCancelable(false);
// nội dung tin nhắn nhủ tới người dùng
pd.setMessage("tôi đang thực hiện");
// cho hiện ra linearlayout
setContentView(ll);
}
public void onClick(View arg0) {
// khởi tạo task
task t = new task(this);
// truyền tham số
t.execute("truyền lệnh ");
}
}
// 3 định kiểu của class AsyncTask là <[tham số],[kiểu giá trị cập nhật],[kiểu trả về]>
class task extends AsyncTask<String, Integer, Void> {
MainActivity main;
// [kieu tra ve] doInBackground([thamso]...){}
public task(MainActivity main) {
this.main = main;
}
// hàm thực thi trước khi thực hiện tham số
public void onPreExecute() {
// cho hiện thi hộp báo
main.pd.show();
}
// hàm thực thi khi truyền tham số thực hiện
protected Void doInBackground(String... str) {
try {
String ms = str[0];
for (int i = 0; i < 10; i++) {
//gửi đến hàm cập nhật giá trị
this.publishProgress(i);
//cho ngủ 1 giây
Thread.sleep(1000);
}
} catch (Exception e) {
}
return null;
}
//hàm thực thi khi lệnh publishProgress được gọi, cập nhật giá trị
public void onProgressUpdate(Integer... i){
int y=(int)i[0];
main.pd.setMessage(y+" giây trôi qua");
}
// hàm thực hiện xong, kết thúc với tham số là kiểu tra về [Void..]
public void onPostExecute(Void t) {
// cho ẩn đi hộp báo khi thực hiện xong
main.pd.dismiss();
}
}
Bạn thấy đó, AsyncTask cần gán 3 kiểu giá trị thực hiện, bao gồm <kiểu tham số đầu vào, kiểu giá trị dùng cho cập nhật công việc, kiểu kết quả trả về>, trên ví dụ trên tôi dùng <String, Integer, Void> có ý nghĩa như sau.
Khi bạn tạo 1 task, và sau đó dùng lệnh .execute(String…) thì tham số được truyền vào String này, mặc định nó có thể là 1 chuỗi, hoặc là 1 array, và khi đó, trong class task, hàm .onPreExecute được thực thi trước, một hộp thoại hiện ra với lệnh .show(), sau đó hàm .doInBackground(String… str) được thực thi, nó nhận tham số như là 1 array, do đó bạn cần chọn ra 1 vị trí của array này để lấy tham số thực hiện.
Trong quá trình thực hiện .doInBackground, bạn có thể dùng hoặc không hàm .publishProgress(kiểu tham số update), ở đây tôi chọn là kiểu Integer tương đương int, cho nên tôi truyền biến i vào cho nó, khi đó 1 hàm khác được thực thi ngay, đó là hàm .onProgressUpdate(Integer… i), ở đây nó cũng nhận tham số như là 1 array, bất kể bạn đưa vào 1 hay 2 giá trị i, do đó cũng phải lấy ra 1 giá trị để cập nhật lên MainActivity.
Cuối cùng, khi đã thực hiện xong hàm .doInBackgroud, nhanh chóng hàm .onPostExecute(kiểu giá trị trả về) được thực hiện, lúc đó ta dọn dẹp những thứ ta cần thiết, và tôi cho hộp thoại biến mất qua hàm .dismiss().