这是我应用的流程:
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
答案 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()
,onPreExecute
doInBackground
,onPostExecute
,因为它在UI线程中运行。您还可以通过调用onPostExecute
在doInBackground
仍在运行时更新您的UI线程。每次调用此方法都将触发UI线程上publishProgress()
的执行。
提示:如果您在onProgressUpdate()
progressDialog
内解除onCancelled()
内的onPostExecute()
一个好主意