如果异步任务被解除,则重新显示进度对话框
Posted
技术标签:
【中文标题】如果异步任务被解除,则重新显示进度对话框【英文标题】:Reshow a progress dialog from Async Task if it gets dismissed 【发布时间】:2021-06-22 07:26:35 【问题描述】:我有一个进度对话框,显示在我的异步任务中还有多少文件要上传,如果用户愿意,可以关闭此对话框。但是我想要一个按钮,它能够在当前阶段再次显示该进度对话框,我不知道该怎么做,因为我不能只在异步任务中创建一个函数并从不同的活动。有什么想法吗?
【问题讨论】:
【参考方案1】:您可以创建一个单例类来处理仅包含一个侦听器(想要侦听 AsyncTask 进度的 Activity)的异步任务进度。 您的 Singleton 类可以如下所示:
public class ProgressDialogUtil
public interface ProgressDialogUtilListener
void showProgressDialog();
void dismissProgressDialog();
void updateProgressDialog(int value);
void setProgressDialogMessage(String message);
private ProgressDialogUtilListener listener;
private static ProgressDialogUtil mInstance;
public static ProgressDialogUtil getInstance()
if (mInstance == null)
synchronized (ProgressDialogUtil.class)
if (mInstance == null)
mInstance = new ProgressDialogUtil();
return mInstance;
public void setListener(ProgressDialogUtilListener listener)
this.listener = listener;
public void showProgressDialog()
if(listener!=null)
listener.showProgressDialog();
public void dismissProgressDialog()
if(listener!=null)
listener.dismissProgressDialog();
public void updateProgressDialog(int value)
setProgressDialogMessage("Files Downloaded: "+ value);
if(listener!=null)
listener.updateProgressDialog(value);
public void setProgressDialogMessage(String message)
if(listener!=null)
listener.setProgressDialogMessage(message);
然后你可以在你的 AsyncTask 中使用这个 Singleton 类 (ProgressDialogUtil) 来通知发生的任何更新:
public class MyAsyncTask extends AsyncTask<Void, Integer, Boolean>
public final ProgressDialogUtil progressDialogUtil;
public MyAsyncTask(ProgressDialogUtil progressDialogUtil)
this.progressDialogUtil = progressDialogUtil;
@MainThread
@Override
protected void onPreExecute()
super.onPreExecute();
progressDialogUtil.setProgressDialogMessage("Start Download files..");
progressDialogUtil.showProgressDialog();
@WorkerThread
@Override
protected Boolean doInBackground(Void... params)
//download your files here in the Background Thread...
//below is a sample loop
for (int i=0; i <= 50; i++)
try
Thread.sleep(1000);
publishProgress(i);
catch (InterruptedException e)
e.printStackTrace();
return false;
return true;
@MainThread
@Override
protected void onProgressUpdate(Integer... values)
super.onProgressUpdate(values);
progressDialogUtil.updateProgressDialog(values[0]);
@MainThread
@Override
protected void onPostExecute(Boolean result)
super.onPostExecute(result);
progressDialogUtil.setProgressDialogMessage("Finished Download!");
progressDialogUtil.dismissProgressDialog();
然后在您启动 AsyncTask 的第一个 Activity 中,您可以创建进度对话框的新实例并设置监听器 ProgressDialogUtilListener 来监听任何 AsyncTask 进度以显示/隐藏/更新进度对话框如下:
ProgressDialog pd = new ProgressDialog(this);
ProgressDialogUtil progressDialogUtil = ProgressDialogUtil.getInstance();
progressDialogUtil.setListener(new ProgressDialogUtil.ProgressDialogUtilListener()
@Override
public void showProgressDialog()
if (!pd.isShowing())
pd.show();
@Override
public void dismissProgressDialog()
if (pd.isShowing())
pd.dismiss();
@Override
public void updateProgressDialog(int value)
pd.setProgress(value);
@Override
public void setProgressDialogMessage(String message)
pd.setMessage(message);
);
new MyAsyncTask(progressDialogUtil).execute();
最后,当您导航到新 Activity 时,您可以使用相同的单例实例 ProgressDialogUtil 并将侦听器更改为新 Activity 现在所有 AsyncTask 事件都将被处理到新 Activity 并且对话框可以通过这个单例类通过按钮打开/关闭,如下所示:
ProgressDialog pd = new ProgressDialog(this);
ProgressDialogUtil progressDialogUtil = ProgressDialogUtil.getInstance();
progressDialogUtil.setListener(new ProgressDialogUtil.ProgressDialogUtilListener()
@Override
public void showProgressDialog()
if (!pd.isShowing())
pd.show();
@Override
public void dismissProgressDialog()
if (pd.isShowing())
pd.dismiss();
@Override
public void updateProgressDialog(int value)
pd.setProgress(value);
@Override
public void setProgressDialogMessage(String message)
pd.setMessage(message);
);
//Show Progress Dialog from a Button Click
showButton.setOnClickListener(new View.OnClickListener()
@Override
public void onClick(View v)
progressDialogUtil.showProgressDialog();
);
//Dismiss Progress Dialog from a Button Click
dismissButton.setOnClickListener(new View.OnClickListener()
@Override
public void onClick(View v)
progressDialogUtil.dismissProgressDialog();
);
【讨论】:
非常感谢!!这实际上看起来可以解决我所有的问题,甚至解决在不同活动中出现进度对话框的问题。尝试后我会将其标记为解决方案! 总是不鼓励使用 Singleton....我更喜欢使用 ViewModel 和 LiveData 来获得更好、更简洁的代码。 en.m.wikipedia.org/wiki/Singleton_pattern#Drawbacks 和code.google.com/p/google-singleton-detector/wiki/… 基本上单例刹车面向对象机制,被过度使用(尤其是新手程序员),就像一个全局变量(全局变量总是不好的),很难测试一个类使用Singletons的,访问Singleton的Resources应该在多线程环境下序列化等等。Java中Singletons的Cons/drawss有很多文章。 @cylegend 不要忘记在活动onDestroy()
回调中调用progressDialogUtil.setListener(null)
,否则当用户导航到另一个活动时可能会导致内存泄漏。
@cylegend 在活动之间共享进度值的唯一可能方法是使用单例模式,或者使用监听器或 LiveData。 AsyncTask 只知道一个实例来发送进度,并且任何 Activity 都可以观察或侦听此进度。 Rajesh.k 他在 onDestroy() 回调中是正确的,您必须设置 progressDialogUtil.setListener(null) 以避免内存泄漏。 Rajesh.k 的答案也是正确的,这是您可以在 Singleton 类中使用 LiveData 的方式。【参考方案2】:
您可以在任何单例类中拥有实时数据,如下所示,以共享活动之间的进度。
object ProgressHelper
val progress = MutableLiveData<Int>()
然后从 AsyncTask 更新进度值,如下所示:
override fun onProgressUpdate(vararg values: Int?)
super.onProgressUpdate(*values)
ProgressHelper.progress.value = 100
在您的活动中,您可以观察如下进度:
ProgressHelper.progress.observe(this, Observer
val progress = it
)
【讨论】:
以上是关于如果异步任务被解除,则重新显示进度对话框的主要内容,如果未能解决你的问题,请参考以下文章
异步任务进度对话框需要很长时间才能完成 android 中的简单任务