如何在AsyncTask / Background-Thread中获得用户反馈(例如来自AlertDialog)?

时间:2014-07-02 09:59:13

标签: android multithreading android-asynctask android-alertdialog messagebox

Android 4+应用应该执行长时间运行的操作。例如,这可能是将一百万个文件从A复制到B.为了不阻止UI,此操作使用AsyncTask在后​​台运行。

假设操作在过程中间需要一些用户反馈以继续其工作,例如"文件XY已存在。覆盖,Irgnore或重命名?"

从用户那里获得此反馈的最佳方式是什么?由于操作在后台线程中运行,因此无法呈现AlertDialog(或类似的东西)因为UI交互只能在主线程中进行...

所以我遇到了这些解决方案:

  1. 在后台主题开始之前要求退款,例如在开始复制/移动文件之前询问如何处理冲突 背景。
  2. 请勿处理冲突,但请注意询问用户 如何在新的操作完成后处理它们 操作即可。
  3. 结束第一次冲突的后台操作,询问用户反馈并继续新的后台操作
  4. 我不喜欢这些解决方案。在第一种情况下,即使根本不存在冲突,也要求用户提供反馈。如果必须按特定顺序处理步骤,则无法实现第二种解决方案。第三种解决方案会导致代码难以阅读/理解/维护。

    一个好的解决方案是:

    • 停止后台主题
    • Marshal到UI线程并获得用户的反馈
    • 恢复后台线程并使用反馈继续操作

    在Objectiv-C / iOS中使用GCD或在C#中使用async / await这不是一个大问题。但是如何使用AsyncTask在Android中完成此操作?

1 个答案:

答案 0 :(得分:0)

同时我想,我找到了答案here:只需在myActivity.runOnUiThread(...)内运行doInBackground(...)并等待它。听起来不错,但它不起作用。 AsyncTask /后台线程不等待Runnable完成:

private void copyFiles() {
    CopyTask copyTask = new CopyTask (this);
    copyTask.execute();
}

private class CopyTask extends CustomAsyncTask<Void, Void, Void> {
    private doCopy;

    @Override
    protected Boolean doInBackground(Void... params) {              
        // Custom code, e.g. copy files from A to B and check for conflict
        for (File file : allFiles) {
            doCopy = true;

            if (isConflict(file)) {
                // Stop current thread and ask for user feedback on UI Thread

                Runnable uiRunnable = new Runnable() {
                    public void run() {
                        // Pos 1. --> Execute custom code, e.g. use AlertDialog to ask user if file should be replaced...
                        doCopy = false;

                        synchronized (this) {
                           this.notify();
                        }
                    }
                });  

                synchronized(uiRunnable) {
                    // Execute code on UI thread
                    activity.runOnUiThread(uiRunnable);

                    // Wait until runnable finished
                    try {
                        uiRunnable.wait();
                    }
                    catch (InterruptedException e ) {
                        e.printStackTrace();
                    }
                }
            }

            // Pos 2. --> Continue work
            if (doCopy)
               copyFromAToB(File);
        }

        return null;
    }
}

我希望,当检测到冲突时,执行Runnable并执行 Pos 1 Runnable内的代码以解决冲突) BEVOR到达Pos 2 。不是这种情况。 Runnable已正确执行,但AsyncTask并未等待它完成。 doInBackground的执行继续执行而没有任何中断。似乎doInBackgroundRunnable并行执行(因为它们在不同的线程上执行而不令人惊讶),但为什么doInBackground不等待?