简体   繁体   English

在任务期间显示进度对话框而不阻塞 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();

}

This code should be showing the progress dialog, wait for the task to produce its result, then evaluate the if statement and dismiss the dialog.此代码应显示进度对话框,等待任务产生其结果,然后评估if语句并关闭对话框。 But this doesn't happen: the UI thread is blocked, the task is executed and only then is the progress dialog shown, only to be dismissed immediately.但这不会发生:UI 线程被阻塞,任务被执行,然后才显示进度对话框,然后立即解除。

What would be the correct way to solve this problem ?解决这个问题的正确方法是什么?

A simple worker thread .一个简单的工作线程

public void onClick(View v) {
    new Thread(new Runnable() {
        public void run() {
            // a potentially time consuming task
        }
    }).start();
}

There are other alternatives that can be considered depending on your requirement as mentioned in this answer .如本答案中所述,根据您的要求,可以考虑其他替代方案。

You can use AsyncTask for this purpose, however, it has been deprecated in Sdk 30 and recommended to use the java.concurrent.* utilities directly docs .您可以为此目的使用 AsyncTask,但是,它在 Sdk 30 中已被弃用,并建议直接使用 java.concurrent.* 实用程序docs Following is an workaround using ExecutorService, although it is not perfect, it definitely meets your functionality:下面是一个使用ExecutorService的解决方法,虽然不完美,但绝对满足你的功能:

In your Activity (say, MyActivity), create a member of ExecutorService and initialize it.在您的 Activity(例如 MyActivity)中,创建 ExecutorService 的成员并对其进行初始化。 Add method and callback like following, when you want to perform some background task, just call it:添加方法和回调如下,当你想执行一些后台任务时,只需调用它:

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

When you are done, just shut down the ExecutorService.完成后,只需关闭 ExecutorService。 This Executor and related methods can be moved into ViewModel if you use them for better design.如果您使用它们进行更好的设计,则可以将这个 Executor 和相关方法移到 ViewModel 中。 Remember, you should not use Thread directly to avoid potential memory leak.请记住,您不应直接使用 Thread 以避免潜在的内存泄漏。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM