Tui sẽ trình bày sơ qua về lý thuyết của AsyncTask trước khi vào những ví dụ cụ thể:
Bạn xem hình chụp 1 sau (bạn nhìn vào các đường mũi tên trỏ các parameter):
và hình số 2 sau như (nhìn vào các đường chỉ parameter):
– Tui sẽ giải thích kỹ về vấn đề này:
Trong AsyncTask<Params, Progress, Result> có 3 đối số là các Generic Type:
Params: Là giá trị ((biến) được truyền vào khi gọi thực thi tiến trình và nó sẽ được truyền vào doInBackground
Progress: Là giá trị (biến) dùng để update giao diện diện lúc tiến trình thực thi, biến này sẽ được truyền vào hàm onProgressUpdate.
Result: Là biến dùng để lưu trữ kết quả trả về sau khi tiến trình thực hiện xong.
Những đối số nào không sử dụng trong quá trình thực thi tiến trình thì ta thay bằng Void.
Thông thường trong 1 AsyncTask sẽ chứa 4 hàm, đó là :
onPreExecute() : Tự động được gọi đầu tiên khi tiến trình được kích hoạt.
doInBackground(): Được thực thi trong quá trình tiến trình chạy nền, thông qua hàm này để ta gọi hàm onProgressUpdate để cập nhật giao diện (gọi lệnh publishProgress). Ta không thể cập nhật giao diện trong hàm doInBackground().
onProgressUpdate (): Dùng để cập nhật giao diện lúc runtime
onPostExecute(): Sau khi tiến trình kết thúc thì hàm này sẽ tự động sảy ra. Ta có thể lấy được kết quả trả về sau khi thực hiện tiến trình kết thúc ở đây.
Trong 4 hàm trên thì hàm doInBackground() bắt buộc phải tồn tại, còn các hàm khác có thể khuyết, nhưng theo Tui các bạn nên sử dụng đầy đủ 4 hàm đã nêu.
Đối với AsyncTask thì ta cần tạo một lớp kế thừa từ AsyncTask, sau đó từ MainActivity ta gọi hàm execute() của tiến trình này là OK.
Sau đây Tui sẽ làm một ví dụ cập nhật ProgressBar bằng AsyncTask (tui đã làm bằng Handler class trong bài 34):
– Bài ví dụ trên chỉ đơn giản là cập nhật Progressbar (không quản lý kết quả trả về), nên đối số 1 và đối số 3 ta để Void, đối số 2 ta để Integer.
– Bạn tạo một Project như hình chụp dưới đây (với MyAsyncTask kết thừa từ AsyncTask):
– Layout XML tương tự như bài 34:
[code language=”xml”]
[/code]
– Bạn xem Tui giải thích source code MyAsyncTask dưới này:
[code language=”java”]
package tranduythanh.com;
import android.app.Activity;
import android.os.AsyncTask;
import android.os.SystemClock;
import android.widget.ProgressBar;
import android.widget.TextView;
import android.widget.Toast;
public class MyAsyncTask
extends AsyncTask {
//khai báo Activity để lưu trữ địa chỉ của MainActivity
Activity contextCha;
//constructor này được truyền vào là MainActivity
public MyAsyncTask(Activity ctx)
{
contextCha=ctx;
}
//hàm này sẽ được thực hiện đầu tiên
@Override
protected void onPreExecute() {
// TODO Auto-generated method stub
super.onPreExecute();
Toast.makeText(contextCha, “onPreExecute!”,
Toast.LENGTH_LONG).show();
}
//sau đó tới hàm doInBackground
//tuyệt đối không được cập nhật giao diện trong hàm này
@Override
protected Void doInBackground(Void… arg0) {
for(int i=0;i<=100;i++)
{
//nghỉ 100 milisecond thì tiến hành update UI
SystemClock.sleep(100);
//khi gọi hàm này thì onProgressUpdate sẽ thực thi
publishProgress(i);
}
return null;
}
/**
* ta cập nhập giao diện trong hàm này
*/
@Override
protected void onProgressUpdate(Integer… values) {
// TODO Auto-generated method stub
super.onProgressUpdate(values);
//thông qua contextCha để lấy được control trong MainActivity
ProgressBar paCha=(ProgressBar) contextCha
.findViewById(R.id.progressBar1);
//vì publishProgress chỉ truyền 1 đối số
//nên mảng values chỉ có 1 phần tử
int giatri=values[0];
//tăng giá trị của Progressbar lên
paCha.setProgress(giatri);
//đồng thời hiện thị giá trị là % lên TextView
TextView txtmsg=(TextView)
contextCha.findViewById(R.id.textView1);
txtmsg.setText(giatri+"%");
}
/**
* sau khi tiến trình thực hiện xong thì hàm này sảy ra
*/
@Override
protected void onPostExecute(Void result) {
// TODO Auto-generated method stub
super.onPostExecute(result);
Toast.makeText(contextCha, "Update xong roi do!",
Toast.LENGTH_LONG).show();
}
/**
* tui làm 2 hàm ví dụ này về params trong Android
*/
public void goividu()
{
viduParamschoham();
viduParamschoham(5);
viduParamschoham(5,6);
viduParamschoham(5,6,5,6,7,8,9,0,0);
}
/**
* dấu … dùng khai báo param
* tức là ta truyền bao nhiêu đối số cũng được
* ds trở thành mảng 1 chiều
* @param ds
*/
public void viduParamschoham(int … ds)
{
//test chơi…
int pt0=ds[0];//có lỗi nếu như không truyền đối số nào
for(int n:ds)
{
System.out.println(n);
}
//hoặc
for(int i=0;i<ds.length;i++)
{
System.out.println(ds[i]);
}
}
}
[/code]
– Ở đoạn code trên có 2 hàm cuối cùng là Tui viết thêm vào để giải thích cho việc sử dụng params trong Java, bạn cố gắng đọc để hiểu.
– Tiến trình MyASyncTask sẽ được thực thi khi bên MainActivity ta gọi phương thức: .execute()
source code MainActivity:
[code language=”java”]
package tranduythanh.com;
import android.os.Bundle;
import android.app.Activity;
import android.view.Menu;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
public class MainActivity extends Activity {
Button btnStart;
//khai báo MyAsyncTask
MyAsyncTask mytt;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
btnStart=(Button) findViewById(R.id.button1);
btnStart.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View arg0) {
// TODO Auto-generated method stub
doStart();
}
});
}
private void doStart()
{
//truyền this (chính là MainActivity hiện tại) qua Child Thread
mytt =new MyAsyncTask(this);
//Kích hoạt Tiến trình
//khi gọi hàm này thì onPreExecute của mytt sẽ thực thi trước
mytt.execute();
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.activity_main, menu);
return true;
}
}
[/code]
– Vô cùng đơn giản….. mọi thứ đẩy về cho Child Thread.
– Bạn có thể tải coding mẫu ở đây: http://www.mediafire.com/download/9or85fvafatp14o/LearnMultiThreading_ProgressBar_AsyncTask.rar
– Trong bài kế tiếp Tui sẽ làm 1 ví dụ AsyncTask nhưng có quản lý kết quả trả về, bài này tương đối phức tạp, các bạn chú ý theo dõi
– Chúc các bạn thành công!
cho tôi hỏi là : khi chạy 1 app, và đối tượng 1 sẽ hoạt động không dừng ( ví dụ : di chuyển qua lại mãi mãi) . và hành động khác được chạy xen vào( ví dụ : ta touch vào đối tượng thì đối tượng đó xoay 1 vòng) và hành động 1 dừng lại chờ hành động 2 thực thi xong thì chạy tiếp. thì ta phải dùng asynctask như thế nào ak ?
e cảm ơn thầy những bài viết của thầy rất hay 😀 e chúc thầy có sức khỏe ,hi vọng thầy sẽ ra tip những bài mới 😀
Thầy ơi cho e hỏi là 2 cái hàm này “public void goividu()” và “public void viduParamschoham(int … ds)” dùng để làm gì?
– Ở đoạn code trên có 2 hàm cuối cùng là Tui viết thêm vào để giải thích cho việc sử dụng params trong Java, bạn cố gắng đọc để hiểu.
asynctask có phải tương tự như thread ko a?
muốn xóa asynctask đã tạo ra thì làm ntn ạ?
Quá hay luôn thầy ơi,tks thầy chia sẻ tỷ mỷ như vậy :))
@Duẫn : thầy nói quá rõ ràng rồi bạn,mình xin nói lại theo cách hiểu của mình nha ,nếu như bạn muốn tạo một hàm nào đó dùng chung có các tham số cùng kiểu dl,thay vì bạn mắc công chèn 1,2 hay 3 tham số vàomột hàm,rồi một lúc nào đó cần làm bài toán khác với số lượng các tham số khác nữa như vậy mắc thời gian tạo lại,vì vậy bạn tạo một hàm với kdl bạn muốn rồi dùng “…” như ngụ ý bạn muốn đưa vào bao nhiêu tham số cũng được tùy theo bài toán của bạn,ví dụ ở vd của thầy,bạn muốn sử dụng hàm viduParamschoham(int … ds) cho bài toán với 1 tham số truyền vào,khi khác lại dùng với 2, hay 3 hoặc lên đến 4,5 tham số gì đó thì bạn dùng lại hàm này vẫn ok,mình chỉ nói theo cách của mình hiểu thôi,hy vọng rằng đúng :))
Bài viết của thầy rất hay,rất dễ hiểu ạ
Em có câu hỏi là: Làm sao để Pause được Thread bằng AsyncTask?
Multi Thread nhưng lại ko Asynchronous như Handler. Ko hiểu tại sao ?
Em có câu hỏi là : Em dùng Hanlder class và xử lý runtime. Tức là em dùng Hanlder class để call 1 URL trên webserice sau đó. Nếu có giá trị thì em sẽ xử lý. Em cho lặp lại trong 1s. Nếu không có dữ liệu thì thôi. Nhưng sau khi dùng 1 thời gian thì ứng dụng của em bị treo. Em không hiểu gì sao. Nó chỉ pause lại Mainacitivy. Mong thấy giúp em. Hoặc em muốn hỏi là có cách nào khác để sync android không? Em mới học android
Hi em,
Em request liên tục 1s thì server nào mà chịu nổi … Server tự cấm em luôn. Với lại em cần liệt kê chi tiết chút xíu về service và cách em tương tác
mọi người cho mình hỏi mình tạo 1 cái app music, mình dùng asyntask để cập nhật thanh seekbar, bằng cách setProgress (getCurrentDuration ), không hiểu tại sao bản nhạc khi play rất là giật, mình cảm ơn !
E hơi nhầm lẫn chút là: Khi nào nên sử dụng AsyncTask và khi nào thì dùng Service. Vì cả hai đều chạy ngầm