Ở bài tập 37 Tui đã trình bày về cách xử lý đa tiến trình bằng AsyncTask nhưng không quản lý kết quả trả về, trong một số tình huống khi xử lý đa tiến trình chúng ta phải quản lý kết quả thực thi đa tiến trình, vì vậy Tui muốn làm 1 ví dụ cụ thể để các bạn tiện theo dõi và làm theo.
Ở đây tui làm 1 bài đơn giản: Dùng AsyncTask để cứ sau 150 miliseconds thì cập nhật 1 số Fibonacci vào ListView, sau khi kết thúc quá trình cập nhập Fibonacci thì chương trình sẽ hiển thị Tổng giá trị của dãy số Fibonacci này.
– Bạn xem hình Tui chụp dưới này:
– Ở bài này ta cần biết:
1) Số Fibonacci là số gì?
2) Truyền số lượng vào MyAsyncTask như thế nào?
3) Cập nhật vào ListView ?
4) Và lấy kết quả trả về sau khi kết thúc tiến trình?
————————————————————————-
1) Số fibonacci là số fibonacci, vô cùng đơn giản …. các bạn xem ở đây: http://vi.wikipedia.org/wiki/D%C3%A3y_Fibonacci
– Bạn tạo Project như hình dưới đây:
– XML Layout như sau:
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:id="@+id/LinearLayout1" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical" tools:context=".MainActivity" > <LinearLayout android:layout_width="match_parent" android:layout_height="wrap_content" > <Button android:id="@+id/button1" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="OK" /> <EditText android:id="@+id/editText1" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_weight="1" android:ems="10" > <requestFocus /> </EditText> <TextView android:id="@+id/textView1" android:layout_width="wrap_content" android:layout_height="wrap_content" android:background="#008000" android:textColor="#FFFFFF" android:textSize="25sp" /> </LinearLayout> <ListView android:id="@+id/listView1" android:layout_width="match_parent" android:layout_height="wrap_content" > </ListView> </LinearLayout>
– MyAsyncTask Tui sử dụng cả 3 đối số:
package tranduythanh.com; import java.util.ArrayList; import android.app.Activity; import android.os.AsyncTask; import android.os.SystemClock; import android.widget.ArrayAdapter; import android.widget.ListView; import android.widget.TextView; import android.widget.Toast; /** * AsyncTask<Integer, Integer, ArrayList<Integer>> * Integer: Truyền vào lúc thực thi tiến trình * Integer: Giá trị để Cập nhật giao diện * ArrayList<Integer>: Kết quả trả về sau khi kết thúc tiến trình * @author thanhtran * */ public class MyAsyncTask extends AsyncTask<Integer, Integer, ArrayList<Integer>> { Activity activityCha; ListView lv=null; ArrayList<Integer>arrCuaListview=new ArrayList<Integer>(); ArrayAdapter<Integer>adapterCuaListview=null; public MyAsyncTask(Activity act) { //lấy MainActivity activityCha=act; //Lấy ListView của MainActivity lv=(ListView) activityCha.findViewById(R.id.listView1); //Adapter cho Listview adapterCuaListview=new ArrayAdapter<Integer> (activityCha, android.R.layout.simple_list_item_1, arrCuaListview); //gán Adapter cho listview lv.setAdapter(adapterCuaListview); } /** * Số fibonacci thứ n trong chuỗi Fibonacci * @param n * @return */ public int fib(int n) { if(n<=2)return 1; return fib(n-1)+fib(n-2); } @Override protected void onPreExecute() { // TODO Auto-generated method stub super.onPreExecute(); //muốn khởi tạo gì đó trước khi thực thi thì có thể làm ở đây Toast.makeText(activityCha, "Bắt đầu chạy tiến trình ", Toast.LENGTH_LONG).show(); } @Override protected ArrayList<Integer> doInBackground(Integer... arg0) { // TODO Auto-generated method stub //vậy thì khi bắt đầu thực thi đối số 1 sẽ ở đây: arg0 int so=arg0[0]; //khai báo ArrayList lưu trữ tập các số nguyên ArrayList<Integer> arrTongCacSoFib=new ArrayList<Integer>(); for(int i=1;i<=so;i++) { SystemClock.sleep(150); //lấy số fibonacci tại vị trí thứ i int f=fib(i); //lưu vào danh sách arrTongCacSoFib.add(f); //cập nhập số fibonacci lên listview publishProgress(f); } //trả về danh sách, nó sẽ được lưu trữ trong hàm //onPostExecute return arrTongCacSoFib; } @Override protected void onProgressUpdate(Integer... values) { // TODO Auto-generated method stub super.onProgressUpdate(values); //lấy giá trị truyền từ publishProgress arrCuaListview.add(values[0]); //cập nhật lại giao diện adapterCuaListview.notifyDataSetChanged(); } @Override protected void onPostExecute(ArrayList<Integer> result) { // TODO Auto-generated method stub super.onPostExecute(result); //result chính là ArrayList lưu trữ chuỗi Fibonacci int tong=0; //vòng lặp để cộng dồn lại for(int v : result) { tong+=v; } Toast.makeText(activityCha, "Tong ="+tong, Toast.LENGTH_LONG).show(); //cập nhật lên TextView TextView txt=(TextView) activityCha.findViewById(R.id.textView1); txt.setText(tong+""); } }
– Trong coding trên thì phần ListView và Adapter bạn đã được học từ lâu rồi nên không cần giải thích thêm nhiều.
– Tiếp tục vào MainActivity:
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; import android.widget.EditText; public class MainActivity extends Activity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); Button b=(Button) findViewById(R.id.button1); b.setOnClickListener(new OnClickListener() { @Override public void onClick(View arg0) { // TODO Auto-generated method stub doStart(); } }); } private void doStart() { //tạo 1 tiến trình MyAsyncTask tt=new MyAsyncTask(this); EditText edt=(EditText) findViewById(R.id.editText1); //lấy giá trị nhập từu EditText int so=Integer.parseInt(edt.getText()+""); //thực thi tiến trình với đối số truyền vào là so //nó được dùng trong đối số của doInBackground tt.execute(so); } @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; } }
– Bạn thấy Tui gọi lệnh : tt.execute(so); đối số [so] sẽ được truyền vào doinBackground….
– Trong doInBackground, bạn thấy kết quả trả về là ArrayList<Integer> chính là do đối số thứ 3 ta khai báo là ArrayList<Integer>. Thông qua đây để ta lưu trữ được kết quả trong suốt quá trình mà tiến trình thực thi.
– Bạn cố gắng đọc hiểu, chúc bạn thành công!
– Bạn có thể tải coding mẫu ở đây: http://www.mediafire.com/download/e4g8a1cy67lqafq/LearnMultiThreading_GetResult_AsyncTask.rar
– Bài kế tiếp Tui sẽ kết hợp Handler class và AsyncTask class để tạo một Project cập nhập Control lúc runtime, bài này hơi phức tạp, bạn chú ý theo dõi.
thanks thầy!
bài viết rất hay
thầy cho em hỏi là nếu k nhập gì vào edittext khi ấn button thì sẽ báo lỗi.
có cách nào đê xử lý k ạ. em đã thử xét điều kiện ở trong edittext rồi nhưng vẫn không được
bạn có thể sử dụng edittext.getText().toString().equals(“”) để check
thanks!
[…] Bài 38: Lấy kết quả trả về sau khi thực hiện đa tiến trình bằng AsyncTask […]
Cảm ơn bai viết của thầy.
Cho em hỏi như thế nào để dừng AsynTask khi nó đang chạy?
Ứng dụng của em dùng 1 AsynTask để kiểm tra liên tục trạng thái kết nối Internet.
Em dung một lệnh while, khi onPause AsynTask không dừng lại. Em phải lm sao?
cảm ơn thầy . bài viết rất hay . e đã hiểu hơn về Asyns Task . Chúc thầy 1 ngày đầy năng lượng