在任务期间显示进度对话框而不阻塞Android中的UI线程
Posted
技术标签:
【中文标题】在任务期间显示进度对话框而不阻塞Android中的UI线程【英文标题】:Show progress dialog during task without blocking UI thread in Android 【发布时间】:2021-09-21 18:17:40 【问题描述】:@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 线程被阻塞,任务被执行,然后才显示进度对话框,然后立即关闭。
解决这个问题的正确方法是什么?
【问题讨论】:
【参考方案1】:一个简单的worker thread。
public void onClick(View v)
new Thread(new Runnable()
public void run()
// a potentially time consuming task
).start();
根据answer 中提到的您的要求,可以考虑其他替代方案。
【讨论】:
似乎我必须将整个东西包装在其中一个中以将其与 UI 线程分开。谢谢! 你不应该直接使用线程,使用为后台任务设计的各种实用程序。官方文档推荐 Coroutines for Kotlin 和 Java Concurrent utility for Java。还有一些用于后台处理的库。【参考方案2】:您可以为此目的使用 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 以避免潜在的内存泄漏。
【讨论】:
会发生什么样的内存泄漏? 起初,你不能从后台线程更新你的 UI 元素,为了解决这个问题,有线程之间交互的 Handler。其次,如果您运行一个线程来执行长时间运行的任务并且发生配置更改,您的活动会被破坏,但线程会保持活动状态,使用系统资源并可能导致意外行为,除非您正确处理它们。以上是关于在任务期间显示进度对话框而不阻塞Android中的UI线程的主要内容,如果未能解决你的问题,请参考以下文章
异步任务进度对话框需要很长时间才能完成 android 中的简单任务