Giới thiệu
Bài viết minh họa cách chạy AsyncTask với khả năng đặt thời gian chờ (timeout). Mặc dù AsyncTask đã deprecated từ API 30, bài viết vẫn hữu ích cho bảo trì code cũ. Khuyến nghị dùng Coroutines/Flow (Kotlin) hoặc RxJava/ExecutorService cho dự án mới.
Các bước thực hiện
Bước 1: Tạo dự án mới
Android Studio → File → New Project → Empty Activity.
Bước 2: Giao diện (res/layout/activity_main.xml)
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="https://schemas.android.com/apk/res/android"
xmlns:tools="https://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:padding="16dp"
tools:context=".MainActivity">
<EditText
android:id="@+id/enterTime"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="50dp"
android:layout_centerHorizontal="true"
android:background="@android:drawable/editbox_background"
android:inputType="number"
android:hint="Nhập giây" />
<Button
android:id="@+id/btnRun"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_below="@+id/enterTime"
android:layout_centerHorizontal="true"
android:text="Chạy AsyncTask" />
</RelativeLayout>
Bước 3: Logic (src/MainActivity.java)
import androidx.appcompat.app.AppCompatActivity;
import android.app.ProgressDialog;
import android.os.AsyncTask;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;
import android.widget.Toast;
public class MainActivity extends AppCompatActivity {
Button button;
EditText editTextTime;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
button = findViewById(R.id.btnRun);
editTextTime = findViewById(R.id.enterTime);
button.setOnClickListener(v -> {
AsyncTaskRunner runner = new AsyncTaskRunner();
String sleepTime = editTextTime.getText().toString();
runner.execute(sleepTime);
});
}
private class AsyncTaskRunner extends AsyncTask<String, String, String> {
ProgressDialog progressDialog;
@Override
protected void onPreExecute() {
progressDialog = ProgressDialog.show(MainActivity.this,
"ProgressDialog",
"Chờ " + editTextTime.getText().toString() + " giây");
}
@Override
protected String doInBackground(String... params) {
publishProgress("AsyncTask bắt đầu...");
String resp;
try {
int time = Integer.parseInt(params[0]) * 1000;
Thread.sleep(time); // Giả lập công việc nặng
resp = "Đã ngủ " + params[0] + " giây";
} catch (Exception e) {
e.printStackTrace();
resp = e.getMessage();
}
return resp;
}
@Override
protected void onProgressUpdate(String... text) {
Toast.makeText(MainActivity.this, text[0], Toast.LENGTH_SHORT).show();
}
@Override
protected void onPostExecute(String result) {
progressDialog.dismiss();
Toast.makeText(MainActivity.this, "AsyncTask kết thúc: " + result, Toast.LENGTH_SHORT).show();
}
}
}
Bước 4: Thêm Timeout (Mở rộng)
AsyncTask không có timeout built-in. Cách thực hiện timeout:
// Cách 1: Sử dụng Future.get(timeout) - Chạy AsyncTask trên ExecutorService
ExecutorService executor = Executors.newSingleThreadExecutor();
Future<String> future = executor.submit(() -> {
// Chạy code doInBackground ở đây
Thread.sleep(5000);
return "Done";
});
try {
String result = future.get(3, TimeUnit.SECONDS); // Timeout 3 giây
} catch (TimeoutException e) {
future.cancel(true); // Hủy task
// Xử lý timeout
}
// Cách 2: Kiểm tra isCancelled() trong doInBackground (cooperative cancellation)
@Override
protected String doInBackground(String... params) {
for (int i = 0; i < 100; i++) {
if (isCancelled()) break; // Kiểm tra cờ hủy
// Làm việc từng chút
}
return "Done";
}
// Hủy từ UI thread:
asyncTask.cancel(true); // true = mayInterruptIfRunning
Bước 5: Manifest
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="https://schemas.android.com/apk/res/android"
package="app.com.sample">
<application
android:allowBackup="true"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:roundIcon="@mipmap/ic_launcher_round"
android:supportsRtl="true"
android:theme="@style/AppTheme">
<activity android:name=".MainActivity">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application>
</manifest>
Chạy ứng dụng
Nhập số giây (vd: 5) → nhấn Chạy AsyncTask → ProgressDialog hiện ra → sau 5 giây tự đóng.

Tại sao AsyncTask bị deprecated?
- Rò rỉ bộ nhớ (memory leak) do giữ reference Activity
- Hành vi không nhất quán giữa các phiên bản Android
- Khó xử lý lỗi, timeout, hủy bỏ
- Không hỗ trợ composition, retry, backpressure
Thay thế hiện đại
| Công nghệ | Ngôn ngữ | Đặc điểm |
|---|---|---|
| Kotlin Coroutines | Kotlin | Structured concurrency, suspend functions, timeout() built-in |
| RxJava | Java/Kotlin | Reactive streams, timeout operator, backpressure |
| ExecutorService + CompletableFuture | Java | Future.get(timeout), cancel(), composition |
| WorkManager | Java/Kotlin | Deferred background work, guaranteed execution |