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) ...
- 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); } }