Bài 38: Lấy kết quả trả về sau khi thực hiện đa tiến trình bằng AsyncTask


Ở 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:

async3

– Ở 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:

async4

– 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.

6 responses

  1. 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

    1. bạn có thể sử dụng edittext.getText().toString().equals(“”) để check

      1. thanks!

  2. […] Bài 38: Lấy kết quả trả về sau khi thực hiện đa tiến trình bằng AsyncTask […]

  3. 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?

  4. 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

Leave a comment

This site uses Akismet to reduce spam. Learn how your comment data is processed.