【问题标题】:Display ProgressDialog until AsyncTask finishes, then update UI显示 ProgressDialog 直到 AsyncTask 完成,然后更新 UI
【发布时间】:2015-03-08 21:27:21
【问题描述】:

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

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

【问题讨论】:

  • 我不能真正得到你想要的,但是这个答案是正确的here 会告诉你如何构建你的异步任务,还要注意你的代码需求,我认为你不需要检查路径直接主线程,我认为异步任务有方法可以访问 ui,所以用它来检查你的对象路径,如果它真正调用 postexecute 并做你的事情,希望它有帮助

标签: java android multithreading android-asynctask


【解决方案1】:

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

【讨论】:

  • 这意味着如果异步任务在某个不同的自定义类中,我需要实例化我的 Activity,因为我不会让 getActivity() 在那里做类似((YourActivity)getActivity()).taskComplete(); 之类的事情,或者有更好的方法吗?
  • @eRaisedToX AsyncTask 需要知道Activity 将显示什么ProgressDialog,因此您需要某种参考。怎么做由你决定。
【解决方案2】:

主线程之前似乎没有等待结果 继续。

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

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

AsyncTask 任务完成后,您无需继续在主线程上更新 UI,您只需在解除progressDialog,即progressDialog.dismiss();,因为onPostExecute在UI线程中运行。

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

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

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

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

提示:最好在 onCancelled() 方法中关闭 progressDialog 并在 onPostExecute() 中关闭它,以防万一您在 doInBackground 中取消您的任务

【讨论】:

    【解决方案3】:

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

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-08-13
      • 2018-05-17
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多