Android – AsyncTask – Xử lý bất đồng bộ

Posted: 25/03/2013 in Android
  1.  Android – AsyncTask – Xử lý bất đồng bộ

    1. Giới thiệu:
    – AsyncTask là 1 class hỗ trợ, cung cấp cơ chế thuận tiện để di chuyển những xử lý tốn thời gian vào những tiến trình chạy ngầm ( background thread). Nó cung cấp các sự kiện xử lý đồng bộ, đưa ra kết quả khi tiến thành hoàn thành.
    – AsyncTask bao gồm 1 tiến trình chạy ngầm và một UI cập nhật kết quả khi tiến trình kết thúc(theo “Professional Android 2 Application”)
    2. Để tạo task bất đồng bộ này thì cần extend AsyncTask. Cần chỉ định một class thực hiện phương thức execute , với format sau :
    AsyncTask<[Loại Tham số truyền vào], [Loại update],[Loại kết quả trả về]>
    Nếu không muốn sử dụng tham số truyền vào, tiến độ update, hoặc kết quả trả về, sử dụng Void cho tất cả.

    Ví dụ:
    Tạo class MyAsyncTask

    PHP Code:
    private class MyAsyncTask extends AsyncTask<String, Integer, Integer>{
    //bat dau khoi chay
    @Override
    protected void onPreExecute() {
    // TODO Auto-generated method stub
    super.onPreExecute();
    }
    //tien trinh chay ngam
    @Override
    protected Integer doInBackground(String... params) {
    // TODO Auto-generated method stub
    return null;
    }

    //update ket qua cua tien trinh chay ngam
    @Override
    protected void onProgressUpdate(Integer... values) {
    // TODO Auto-generated method stub
    super.onProgressUpdate(values);
    }

    //sau khi finish tien trinh chay ngam
    @Override
    protected void onPostExecute(Integer result) {
    // TODO Auto-generated method stub
    super.onPostExecute(result);
    }
    }

    – Trong đó các hàm cần chú ý :
    onPreExecute : hàm này sẽ chạy đầu tiên khi class được gọi.
    doInBackground: đây là phương thức chạy background nên NÓ KHÔNG ĐƯỢC TƯƠNG TÁC VỚI OBJECT Ui (vd như set text cho textview hay showToast ở đây là không được…). ở đây đặt phần code xử lý tốn thời gian vào, và sử dụng phương thức publishProgress để cho phép phương thức onProgressUpdate() update lên UI.
    Khi tiến trình này kết thúc , trả về kết quả cuối cùng cho xử lý onPostExecute.
    onProgressUpdate: nhận các thông số thông qua phương thức publishProgress trong doInBackground. Phương thức này thì đồng bộ với UI đang chạy.
    onPostExecute: là phương thức được gọi khi doInBackground hoàn thành.
    Để cho dễ hiểu lấy ví dụ thế này:
    – Bạn thực hiện một phương thức dowdload một tập tin. Bạn xử lý như sau: hiện lên một progress thông báo % của quá trình download, và hiển thì thông báo thành công khi hoàn thành download. Như vậy thì ở :
    – onPreExecute : sẽ hiển thị thanh progress đang ở 0%.
    – doInBackground : thực hiện download, trong này bạn xử lý để lấy được % download là n, bàn dùng phương thức publishProgress để truyền n ra ngoài. Chú ý là trong này bạn không thể update cái progress lên n% được được.
    – onProgressUpdate : nhận được n và bạn sẽ update cho progress lên n %.
    – onPostExecute : kết thúc download, hiện thị Toast thông báo download thành công.

    3.DEMO
    giả sử đây là 1 Task download một bài hát trên mạng. quá trình download sẽ chuyển vào Thread chạy ngầm, màn hình hiển thị phần trăm download. Khi ấn phím back hoặc khi finish download sẽ kết thúc Thread.

    Biến

    PHP Code:
    private Context mContext = null;
    private ProgressDialog mProgressDialog = null; //progress bar thong bao % download
    private RelativeLayout layoutBackground = null; // layout background
    private Button btnAgain = null; // button download lai

    File xml

    PHP Code:
    <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:id="@+id/background" >

    <TextView
    android:layout_width=”wrap_content”
    android:layout_height=”wrap_content”
    android:layout_centerHorizontal=”true”
    android:layout_centerVertical=”true”
    android:padding=”@dimen/padding_medium”
    android:text=”@string/hello_world”
    tools:context=”.AsyncTaskActivity” />
    <Button
    android:id=”@+id/btnAgain”
    android:layout_width=”wrap_content”
    android:layout_height=”wrap_content”
    android:text=”@string/again”
    android:visibility=”gone”/>
    </RelativeLayout>

    Khởi tạo

    PHP Code:
     @Override
    public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_async);
    mContext = this;
    layoutBackground = (RelativeLayout) findViewById(R.id.background);
    btnAgain = (Button) findViewById(R.id.btnAgain);
    btnAgain.setOnClickListener(new OnClickListener() {

    @Override
    public void onClick(View v) {
    btnAgain.setVisibility(View.GONE);
    new MyAsyncTask().execute("android4vn");
    }
    });

    //google analytics dem xem co bao nhiu ng test cai app nay :D
    try {
    GoogleAnaTool.start(mContext);
    GoogleAnaTool.track("/TUT_AsyncTask");
    } catch (Exception e) {
    Log.e(TAG, "error connection....");
    e.printStackTrace();
    }

    new MyAsyncTask().execute("android4vn"); //start Task download
    }

    Phần xử lý và hiển thị phần trăm download

    PHP Code:
    private class MyAsyncTask extends AsyncTask<String, Integer, Integer>{
    boolean isCancel = false;
    @Override
    protected void onPreExecute() {
    // TODO Khoi tao
    super.onPreExecute();
    mProgressDialog = new ProgressDialog(AsyncTaskActivity.this);
    mProgressDialog.setTitle("Android4VN");
    mProgressDialog.setMessage(getString(R.string.begin));
    mProgressDialog.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL);
    mProgressDialog.setMax(100);
    mProgressDialog.show();
    mProgressDialog.setOnCancelListener(new DialogInterface.OnCancelListener() {
    @Override
    public void onCancel(DialogInterface dialog) {
    isCancel = true;
    }
    });
    }
    @Override
    protected Integer doInBackground(String... params) {
    // TODO background
    int nDownload = 0;
    try {
    while(nDownload < 100 && !isCancel){
    Thread.sleep(100);
    Log.v(TAG, "download:" + nDownload);
    nDownload += 1;
    publishProgress(nDownload);
    }
    } catch (Exception e) {
    }
    return nDownload;
    }
    @Override
    protected void onProgressUpdate(Integer... values) {
    // TODO update
    Log.v(TAG, "update: " + values[0]);
    super.onProgressUpdate(values);
    mProgressDialog.setProgress(values[0]);
    if(values[0] == 25){
    mProgressDialog.setMessage(getString(R.string.step2));
    layoutBackground.setBackgroundResource(R.drawable.p3);
    }
    if(values[0] == 50){
    mProgressDialog.setMessage(getString(R.string.step3));
    layoutBackground.setBackgroundResource(R.drawable.p2);
    }
    if(values[0] == 75){
    mProgressDialog.setMessage(getString(R.string.step4));
    layoutBackground.setBackgroundResource(R.drawable.p9);
    }
    }
    @Override
    protected void onPostExecute(Integer result) {
    // TODO Finish
    super.onPostExecute(result);
    mProgressDialog.dismiss();
    Toast.makeText(mContext, "finish at :" + result + " %", Toast.LENGTH_SHORT).show();
    if(result == 100){
    layoutBackground.setBackgroundResource(R.drawable.p8);
    }else{
    layoutBackground.setBackgroundColor(android.R.color.white);
    }
    btnAgain.setVisibility(View.VISIBLE);
    }
    }

    ở trên dùng Thread.sleep để giả sử quá trình Download. Ta dùng publishProgress() để update phần trăm download ra cho onProgressUpdate() lấy hiển thị lên DialogBar và thay đổi hình nền.
    – CUối cùng khi ấn Back hoặc finish thì onPostExecute được gọi

    Xong, source code : http://www.mediafire.com/?6wm52647ibcay3p

Advertisements

Trả lời

Mời bạn điền thông tin vào ô dưới đây hoặc kích vào một biểu tượng để đăng nhập:

WordPress.com Logo

Bạn đang bình luận bằng tài khoản WordPress.com Đăng xuất / Thay đổi )

Twitter picture

Bạn đang bình luận bằng tài khoản Twitter Đăng xuất / Thay đổi )

Facebook photo

Bạn đang bình luận bằng tài khoản Facebook Đăng xuất / Thay đổi )

Google+ photo

Bạn đang bình luận bằng tài khoản Google+ Đăng xuất / Thay đổi )

Connecting to %s