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

时间:2015-01-10 18:14:09

标签: java android multithreading android-asynctask

这是我应用的流程:

1)用户拍摄照片或视频

2)媒体保存到内部存储

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

4)更新UI以指示用户可以继续

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

我想做什么:显示ProgressDialog直到doInBackground()完成,然后将路径分配给我的对象,然后继续在主线程上更新用户界面。

现在,主线程将在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

3 个答案:

答案 0 :(得分:3)

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

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

答案 1 :(得分:2)

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

答案 2 :(得分:2)

  

主线程似乎还没等到之前的结果   仍在进行中。

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

  

然后继续在主线程上更新UI。

AsyncTask任务完成后,您不需要继续主线程来更新UI,您只需执行 post doInBackground任务即可解除onPostExecute()之后的progressDialog,即progressDialog.dismiss();因为onPostExecute在UI线程中运行。

另外,好方法是在progressDialog方法中启动onPreExecute()并在onPostExecute中将其关闭,而不检查progessDialog是否仍然显示,因为{{1}只有在onPostExecute()方法完成其工作时才会运行。

  

我想做什么:在doInBackground()之前显示ProgressDialog   完成,然后将路径分配给我的对象,然后继续   用于更新UI的主线程。

  • doInBackground()
  • 中启动ProgressDialog
  • onPreExecute
  • 中指定对象的路径
  • doInBackground
  • 中解除ProgressDialog
  • 继续主线程工作onPostExecute,因为它在UI线程中运行。

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

提示:如果您在onProgressUpdate()

中取消任务,请忽略在progressDialog内解除onCancelled()内的onPostExecute()一个好主意