12/08/2018, 14:06

Xử Lý Đa Tiến Trình Trong Android Bằng AsyncTask

Giới thiệu AsyncTask trong Android AsyncTask là phương tiện khác để xử lý công việc sử dụng background thread và giao tiếp với UI thread mà không dùng Thread hay Handler Trong AsyncTask<Params, Progress, Result> có 3 đối số là các Generic Type: +) Params: Là giá trị ((biến) ...

  1. Giới thiệu AsyncTask trong Android
  • AsyncTask là phương tiện khác để xử lý công việc sử dụng background thread và giao tiếp với UI thread mà không dùng Thread hay Handler

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 xả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 các bạn nên sử dụng đầy đủ 4 hàm đã nêu.

2. Demo sử dụng AsyncTask trong Android

  • Sau đây mình sẽ hướng dẫn các bạn làm 1 ví dụ có sử dụng AsyncTask. Ví dụ như sau. Mình có 1 progressbar, khi ấn nút start mình sẽ sử dụng AsyncTask để load progressbar và cập nhập textview ở phía trên. Sau đây là hướng dẫn chi tiết

B1. Tạo project mới

B2. Thiết kế giao diện chính như sau

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_awidth="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical"
    app:layout_behavior="@string/appbar_scrolling_view_behavior"
    tools:context="nguyendinhduy.com.asynctaskdemo.MainActivity"
    tools:showIn="@layout/activity_main">

    <TextView
        android:id="@+id/txtStatus"
        android:layout_awidth="wrap_content"
        android:layout_height="wrap_content"
        android:layout_gravity="center"
        android:layout_marginTop="20dp"
        android:text="0%"
        android:textColor="#2c02ff"
        android:textSize="30sp"
        android:textStyle="bold" />

    <ProgressBar
        android:id="@+id/prbDemo"
        style="@style/Base.Widget.AppCompat.ProgressBar.Horizontal"
        android:layout_awidth="match_parent"
        android:layout_height="10dp"
        android:layout_marginTop="15dp" />

    <Button
        android:id="@+id/btnStart"
        android:layout_awidth="150dp"
        android:layout_height="50dp"
        android:layout_gravity="center"
        android:layout_marginTop="20dp"
        android:text="Start" />
</LinearLayout>

B3. Tạo class MyAsyncTask kế thừa AsyncTask.

package nguyendinhduy.com.asynctaskdemo;

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<Void, Integer, Void> {

    Activity contextParent;

    public MyAsyncTask(Activity contextParent) {
        this.contextParent = contextParent;
    }

    @Override
    protected void onPreExecute() {
        super.onPreExecute();
        //Hàm này sẽ chạy đầu tiên khi AsyncTask này được gọi
        //Ở đây mình sẽ thông báo quá trình load bắt đâu "Start"
        Toast.makeText(contextParent, "Start", Toast.LENGTH_SHORT).show();
    }

    @Override
    protected Void doInBackground(Void... params) {
        //Hàm được được hiện tiếp sau hàm onPreExecute()
        //Hàm này thực hiện các tác vụ chạy ngầm
        //Tuyệt đối k vẽ giao diện trong hàm này
        for (int i = 0; i <= 100; i++) {
            SystemClock.sleep(100);
            //khi gọi hàm này thì onProgressUpdate sẽ thực thi
            publishProgress(i);
        }
        return null;
    }

    @Override
    protected void onProgressUpdate(Integer... values) {
        //Hàm thực hiện update giao diện khi có dữ liệu từ hàm doInBackground gửi xuống
        super.onProgressUpdate(values);
        //Thông qua contextCha để lấy được control trong MainActivity
        ProgressBar progressBar = (ProgressBar) contextParent.findViewById(R.id.prbDemo);
        //vì publishProgress chỉ truyền 1 đối số
        //nên mảng values chỉ có 1 phần tử
        int number = values[0];
        //tăng giá trị của Progressbar lên
        progressBar.setProgress(number);
        //đồng thời hiện thị giá trị là % lên TextView
        TextView textView = (TextView) contextParent.findViewById(R.id.txtStatus);
        textView.setText(number + "%");
    }

    @Override
    protected void onPostExecute(Void aVoid) {
        super.onPostExecute(aVoid);
        //Hàm này được thực hiện khi tiến trình kết thúc
        //Ở đây mình thông báo là đã "Finshed" để người dùng biết
        Toast.makeText(contextParent, "Okie, Finished", Toast.LENGTH_SHORT).show();
    }
}

B4. Xử lý code trong MainActivity.java

package nguyendinhduy.com.asynctaskdemo;

import android.os.Bundle;
import android.support.design.widget.FloatingActionButton;
import android.support.design.widget.Snackbar;
import android.support.v7.app.AppCompatActivity;
import android.support.v7.widget.Toolbar;
import android.view.View;
import android.view.Menu;
import android.view.MenuItem;
import android.widget.Button;
import android.widget.ProgressBar;
import android.widget.TextView;

public class MainActivity extends AppCompatActivity {

    Button btnStart;
    MyAsyncTask myAsyncTask;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
        setSupportActionBar(toolbar);
        btnStart = (Button) findViewById(R.id.btnStart);
        btnStart.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                //Khởi tạo tiến trình của bạn
                //Truyền Activity chính là MainActivity sang bên tiến trình của mình
                myAsyncTask = new MyAsyncTask(MainActivity.this);
                //Gọi hàm execute để kích hoạt tiến trình
                myAsyncTask.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.menu_main, menu);
        return true;
    }

    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
        // Handle action bar item clicks here. The action bar will
        // automatically handle clicks on the Home/Up button, so long
        // as you specify a parent activity in AndroidManifest.xml.
        int id = item.getItemId();

        //noinspection SimplifiableIfStatement
        if (id == R.id.action_settings) {
            return true;
        }

        return super.onOptionsItemSelected(item);
    }
}
0