Xử Lý Đa Tiến Trình Trong Android Bằng AsyncTask
Bài đăng này đã không được cập nhật trong 4 năm
- 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_width="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_width="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_width="match_parent"
android:layout_height="10dp"
android:layout_marginTop="15dp" />
<Button
android:id="@+id/btnStart"
android:layout_width="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);
}
}
All rights reserved