简体   繁体   English

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

[英]Display ProgressDialog until AsyncTask finishes, then update UI

This is the flow of my app: 这是我的应用程序的流程:

1) The user takes a picture or video 1)用户拍照或录像

2) The media is saved to internal storage 2)媒体已保存到内部存储器

3) The path is assigned to a custom object 3)路径已分配给自定义对象

4) The UI is updated to indicate that the user can continue 4)更新UI以指示用户可以继续

The UI updates only if the custom object has either an imagepath or a videopath. 仅当自定义对象具有图像路径或视频路径时,UI才会更新。 I've just started using AsyncTask to save to internal storage in a background thread so the app will not hang while saving large files, but I'm having some problems. 我刚开始使用AsyncTask在后台线程中保存到内部存储,因此应用程序在保存大文件时不会挂起,但我遇到了一些问题。

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. 我想做的事:在doInBackground()完成之前显示ProgressDialog ,然后将路径分配给我的Object, 然后继续在主线程上更新UI。

Right now, the main thread will continue while AsyncTask is still working, and the UI will not update correctly since the path has not yet been assigned to the Object. 现在,主线程将在AsyncTask仍在工作时继续,并且UI将无法正确更新,因为路径尚未分配给Object。

I've read about AsyncTask#get() , but I'm not sure how to implement it with the ProgressDialog . 我读过有关AsyncTask#get() ,但我不确定如何使用ProgressDialog实现它。 I tried, and the main thread didn't seem to wait for the results before continuing. 我试过了,主线程似乎并没有等待结果再继续。

I'd really appreciate any help. 我真的很感激任何帮助。 Thank you! 谢谢!

My AsyncTask : 我的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();
        }
    }
}

How I call it, immediately after the user leaves the camera: 用户离开相机后立即如何调用它:

new SaveMediaTask().execute(MEDIA_TYPE_IMAGE);

//WAIT HERE AND DISPLAY PROGRESSDIALOG UNTIL TASK IS DONE

//update UI

Your onPostExecute should notify your activity, that it can continue. 您的onPostExecute应该通知您的活动,该活动可以继续。 So basically: 所以基本上:

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

You can move your code marked with //update UI to the end of your onPostExecute method. 您可以将标记为//update UI代码移动到onPostExecute方法的末尾。 onPostExecute is always called on UI thread and is a good place to update UI to reflect the AsyncTask work results. onPostExecute总是在UI线程上调用,是更新UI以反映AsyncTask工作结果的好地方。

the main thread didn't seem to wait for the results before continuing. 主线程似乎没有等待结果再继续。

the main thread wouldn't wait. 主线程不会等待。 This isn't how AsyncTask work. 这不是AsyncTask工作方式。 AsyncTask runs in background along with your main thread. AsyncTask与您的主线程一起在后台运行。

then continue on the main thread to update the UI. 然后继续在主线程上更新UI。

You don't need to continue on the main thread to update the UI once AsyncTask task is done, you could simply execute that post doInBackground task in onPostExecute() after dismissing the progressDialog , ie progressDialog.dismiss(); 完成AsyncTask任务后,您不需要继续主线程来更新UI,您可以在解除progressDialog之后简单地在onPostExecute()执行该帖子 doInBackground任务,即progressDialog.dismiss(); because onPostExecute runs in the UI thread. 因为onPostExecute在UI线程中运行。

Also, the good way is to start progressDialog inside onPreExecute() method and dismiss it in onPostExecute without checking if the progessDialog is still showing or not because onPostExecute() would only run if the doInBackground() method is finished doing its job. 此外,好的方法是在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. 我想做的事:在doInBackground()完成之前显示ProgressDialog,然后将路径分配给我的Object,然后继续在主线程上更新UI。

  • Start ProgressDialog in onPreExecute , onPreExecute启动ProgressDialog,
  • Assign the path to your object in doInBackground doInBackground指定对象的路径
  • Dismiss ProgressDialog in onPostExecute , onPostExecute关闭ProgressDialog,
  • Continue your main thread work in onPostExecute since it runs in UI thread. 继续你的主线程在onPostExecute工作,因为它在UI线程中运行。

You can also update your UI thread while doInBackground is still running by invoking publishProgress() . 您还可以通过调用publishProgress()doInBackground仍在运行时更新UI线程。 Each call to this method will trigger the execution of onProgressUpdate() on the UI thread. 每次调用此方法都将触发UI线程上onProgressUpdate()的执行。

Tip: Its a good idea to dismiss progressDialog inside onCancelled() method beside dismissing it in onPostExecute() in case if you ever cancel your task inside doInBackground 提示:它是一个好主意,驳回progressDialogonCancelled()方法贬在旁边onPostExecute()的情况下,如果你取消里面你的任务doInBackground

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

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