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

[polldaddy poll=9764234]

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

[code language=”xml”]

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

[/code]

– MyAsyncTask Tui sử dụng cả 3 đối số:

[code language=”java”]

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+"");
}
}

[/code]

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

[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;
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;
}

}

[/code]

– 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 thoughts on “Bài 38: Lấy kết quả trả về sau khi thực hiện đa tiến trình bằng AsyncTask”

  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

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

Leave a Reply