在任务期间显示进度对话框而不阻塞 Android 中的 UI 线程
Show progress dialog during task without blocking UI thread in Android
@Override
protected void onCreate (Bundle savedInstanceState) {
progressDialog.show();
if (/* task that returns a boolean value */) {
// Do stuff
}
else {
// Do other stuff
}
progressDialog.dismiss();
}
此代码应显示进度对话框,等待任务产生结果,然后计算 if
语句并关闭对话框。但这不会发生:UI 线程被阻塞,任务被执行,然后才显示进度对话框,然后立即被关闭。
解决这个问题的正确方法是什么?
一个简单的worker thread.
public void onClick(View v) {
new Thread(new Runnable() {
public void run() {
// a potentially time consuming task
}
}).start();
}
根据您在本 中提到的要求,可以考虑其他替代方案。
您可以为此目的使用 AsyncTask,但是,它已在 Sdk 30 中弃用,建议直接使用 java.concurrent.* 实用程序 docs。以下是使用 ExecutorService 的解决方法,虽然它并不完美,但它绝对满足您的功能:
在您的Activity(例如,MyActivity)中,创建一个ExecutorService 成员并对其进行初始化。添加方法和回调如下,当你想执行一些后台任务时,只需调用它:
public class MyActivity extends AppCompatActivity {
// You can use your preferred executor
private final ExecutorService executor = new ThreadPoolExecutor(0, 1,
3L, TimeUnit.SECONDS,
new LinkedBlockingQueue<>());
@Override
protected void onCreate (Bundle savedInstanceState) {
// Initiate the task
executeParallel(new Callable<Boolean> {
@Override
public Boolean call() {
// Perform your task and return boolean
return trueOrFalse;
}
}, new Callback<Boolean>() {
@Override
public void onStart() {
// Show progress dialog
progressDialog.show();
}
@Override
public void onComplete(Boolean result) {
if (result) {
// Do some tasks
} else {
// Do other tasks
}
// Remove dialog
progressDialog.dismiss();
}
}, new Handler(Looper.getMainLooper()));
}
public <R> void executeParallel(@NonNull Callable<R> callable, @Nullable Callback<R> callback, Handler handler) {
executor.execute(() -> {
handler.post(() -> {
if (callback != null) {
callback.onStart();
}
});
R r = null;
try {
r = callable.call();
} catch (Exception e) {
// Ignore
} finally {
R result = r;
handler.post(() -> {
if (callback != null) {
callback.onComplete(result);
}
});
}
});
}
public interface Callback<R> {
void onStart();
void onComplete(R result);
}
}
完成后,只需关闭 ExecutorService。如果您使用它们进行更好的设计,可以将此 Executor 和相关方法移动到 ViewModel 中。请记住,您不应直接使用 Thread 以避免潜在的内存泄漏。
@Override
protected void onCreate (Bundle savedInstanceState) {
progressDialog.show();
if (/* task that returns a boolean value */) {
// Do stuff
}
else {
// Do other stuff
}
progressDialog.dismiss();
}
此代码应显示进度对话框,等待任务产生结果,然后计算 if
语句并关闭对话框。但这不会发生:UI 线程被阻塞,任务被执行,然后才显示进度对话框,然后立即被关闭。
解决这个问题的正确方法是什么?
一个简单的worker thread.
public void onClick(View v) {
new Thread(new Runnable() {
public void run() {
// a potentially time consuming task
}
}).start();
}
根据您在本
您可以为此目的使用 AsyncTask,但是,它已在 Sdk 30 中弃用,建议直接使用 java.concurrent.* 实用程序 docs。以下是使用 ExecutorService 的解决方法,虽然它并不完美,但它绝对满足您的功能:
在您的Activity(例如,MyActivity)中,创建一个ExecutorService 成员并对其进行初始化。添加方法和回调如下,当你想执行一些后台任务时,只需调用它:
public class MyActivity extends AppCompatActivity {
// You can use your preferred executor
private final ExecutorService executor = new ThreadPoolExecutor(0, 1,
3L, TimeUnit.SECONDS,
new LinkedBlockingQueue<>());
@Override
protected void onCreate (Bundle savedInstanceState) {
// Initiate the task
executeParallel(new Callable<Boolean> {
@Override
public Boolean call() {
// Perform your task and return boolean
return trueOrFalse;
}
}, new Callback<Boolean>() {
@Override
public void onStart() {
// Show progress dialog
progressDialog.show();
}
@Override
public void onComplete(Boolean result) {
if (result) {
// Do some tasks
} else {
// Do other tasks
}
// Remove dialog
progressDialog.dismiss();
}
}, new Handler(Looper.getMainLooper()));
}
public <R> void executeParallel(@NonNull Callable<R> callable, @Nullable Callback<R> callback, Handler handler) {
executor.execute(() -> {
handler.post(() -> {
if (callback != null) {
callback.onStart();
}
});
R r = null;
try {
r = callable.call();
} catch (Exception e) {
// Ignore
} finally {
R result = r;
handler.post(() -> {
if (callback != null) {
callback.onComplete(result);
}
});
}
});
}
public interface Callback<R> {
void onStart();
void onComplete(R result);
}
}
完成后,只需关闭 ExecutorService。如果您使用它们进行更好的设计,可以将此 Executor 和相关方法移动到 ViewModel 中。请记住,您不应直接使用 Thread 以避免潜在的内存泄漏。