显示 ProgressDialog 直到 AsyncTask 完成,然后更新 UI

Display ProgressDialog until AsyncTask finishes, then update UI

这是我的应用程序的流程:

1) 用户拍照或录像

2) 媒体保存到内部存储

3) 路径分配给自定义对象

4) UI 已更新,表示用户可以继续

仅当自定义对象具有图像路径或视频路径时,UI 才会更新。我刚刚开始使用 AsyncTask 在后台线程中保存到内部存储,这样应用程序在保存大文件时不会挂起,但我遇到了一些问题。

我想做的:显示一个ProgressDialog直到doInBackground()完成,然后将路径分配给我的对象,然后然后 继续在主线程上更新 UI.

现在,主线程将继续,而 AsyncTask 仍在工作,并且 UI 将无法正确更新,因为路径尚未分配给对象。

我读过 AsyncTask#get(),但我不确定如何使用 ProgressDialog 来实现它。我试过了,主线程好像没有等到结果就继续了。

非常感谢任何帮助。谢谢!

我的AsyncTask:

private class SaveMediaTask extends AsyncTask<Integer, Void, String>
{
    private ProgressDialog progressDialog;
    private int mediaType;

    public SaveMediaTask()
    {
        progressDialog = new ProgressDialog(getActivity(), ProgressDialog.THEME_HOLO_LIGHT);
        progressDialog.setProgressStyle(ProgressDialog.STYLE_SPINNER);
        this.progressDialog.setTitle("Processing");
    }

    @Override
    protected void onPreExecute()
    {
        super.onPreExecute();
        this.progressDialog.show();
    }

    protected String doInBackground(Integer... mediaType)
    {
        //save to internal storage and return the path
        return path;
    }

    protected void onPostExecute(String path)
    {
        //by the time this runs, the UI has already tried to update itself on the main thread,
        //and found that myObject does not yet have a path. Once this runs, it is too late.
        myObject.setPath(path);

        if (progressDialog.isShowing())
        {
            progressDialog.dismiss();
        }
    }
}

我怎么称呼它,在用户离开相机后立即:

new SaveMediaTask().execute(MEDIA_TYPE_IMAGE);

//WAIT HERE AND DISPLAY PROGRESSDIALOG UNTIL TASK IS DONE

//update UI

您的 onPostExecute 应该通知您的 activity 它可以继续。所以基本上:

// Start the task from your activity
new SaveMediaTask().execute(MEDIA_TYPE_IMAGE);

// Method that will be called when task is completed
public void taskComplete() {
    // update UI
}

...

protected void onPostExecute(String path) {
    myObject.setPath(path);

    if (progressDialog.isShowing()) {
        progressDialog.dismiss();
    }

    ((YourActivity)getActivity()).taskComplete();
}

您可以将标有 //update UI 的代码移至 onPostExecute 方法的末尾。 onPostExecute 总是在 UI 线程上调用,是更新 UI 以反映 AsyncTask 工作结果的好地方。

the main thread didn't seem to wait for the results before continuing.

主线程不会等待。这不是 AsyncTask 的工作方式。 AsyncTask 运行 与您的主线程一起在后台。

then continue on the main thread to update the UI.

一旦 AsyncTask 任务完成,您不需要在主线程上继续更新 UI,您可以简单地执行 post doInBackground 任务在 onPostExecute() 解散 progressDialog 之后,即 progressDialog.dismiss(); 因为 onPostExecute 运行 在 UI 中线程。

此外,好的方法是在 onPreExecute() 方法中启动 progressDialog 并在 onPostExecute 中关闭它而不检查 progessDialog 是否仍在显示,因为 onPostExecute() 只有 运行 如果 doInBackground() 方法完成了它的工作。

What I want to do: Display a ProgressDialog until doInBackground() finishes, then assign the path to my Object, and then continue on the main thread to update the UI.

  • onPreExecute
  • 中启动 ProgressDialog
  • doInBackground
  • 中为您的对象分配路径
  • onPostExecute
  • 中关闭 ProgressDialog
  • 继续您在 onPostExecute 中的主线程工作,因为它 运行 在 UI 线程中。

您还可以在 doInBackground 仍然 运行 时通过调用 publishProgress() 更新您的 UI 线程。每次调用此方法都会触发 UI 线程上的 onProgressUpdate() 的执行。

提示:除了在 onPostExecute() 方法中关闭 progressDialog 方法之外,最好在 progressDialog 方法中关闭它,以防万一您在 doInBackground[= 中取消任务38=]