调用 AsyncTask.get() 时未显示 ProgressDialog [重复]
Posted
技术标签:
【中文标题】调用 AsyncTask.get() 时未显示 ProgressDialog [重复]【英文标题】:ProgressDialog not shown when AsyncTask.get() called [duplicate] 【发布时间】:2012-02-19 14:42:58 【问题描述】:可能重复:AsyncTask block UI threat and show progressbar with delay
我想在从任何服务器检索 JSON 时显示一个 progressDialog。所以我使用 AsyncTask 作为解决方案(不确定有什么不同的出路)。
一切都很好,ProgressDialog 可以正常工作,直到我使用 AsyncTask 实例调用 .get() 方法。我想它以某种方式阻止了用户界面。这是我的 AsyncTask:
public class myAsync extends AsyncTask<String, String, List>
String message; // for dialog message
ProgressDialog progress;
Intent myIntent;
Context ctx;
public myAsync(String message, Context ctx)
this.message = message;
this.ctx = ctx;
progress = new ProgressDialog(ctx);
@Override
protected void onPreExecute()
progress.setMessage(message);
progress.setIndeterminate(true);
progress.setCancelable(false);
progress.show();
@Override
protected List doInBackground(String... params)
//returns any list after the task
return anyList;
@Override
protected void onPostExecute(List result)
if(progress.isShowing())
progress.dismiss();
这是调用 AsyncTask 的 myActivity:
myAsync asyncTask = new myAsync("Loading...", this);
asyncTask.execute("Any string", "Other string");
asyncTask.get(); // If I comment out this line, ProgressDialog works
执行后,当我尝试从 doInBackground 和 onPostExecute 记录结果时,都没有问题。但是如果我想用 .get() 得到结果 ProgressDialog 没有显示或显示时间太短(可能是 0.2 秒)
有什么问题?
【问题讨论】:
你遇到什么异常了吗? 并非如此。正如我所说,对话窗口可以看到这么少的时间。事实上,它至少应该在 2 秒内被看到。 【参考方案1】:是的,get()
等待如果需要完成计算,然后检索其结果。这意味着,您正在阻塞您的 UI 线程,等待结果。
解决方法:不要拨打get
通常,您会在postExecute
中调用一个函数(回调)。
【讨论】:
参见***.com/questions/3291490/… 以获得示例实现 知道了!感谢您的示例,解决了这个问题,但对于不同的主题仍然存在问题。 但是如果我想使用 AsyncTask 的返回值并且基于返回值我想调用新的 URL 那我该怎么做呢?我认为如果有任何选项,我们必须以这种方式使用.get,然后请帮助我 另一种方式:如果您的代码在 UI 线程上执行,则通过新线程包装您的 AsyncTask... 例如)新线程(新 Runnable()....result = yourAsyncTask.execute(). get();.....).start(); 在浪费了 2 个小时后帮助了我。谢谢.. :)【参考方案2】:调用.get()
会将您的AsyncTask
更改为有效的“SyncTask
”,因为它会导致当前线程(将是UI 线程)等待AsyncTask
完成其处理。由于您现在阻塞了 UI 线程,因此对 ProgressDialog
的 .show()
方法的调用永远不会有机会让对话框自行绘制屏幕。
删除调用将使其在后台正常运行。
如果您需要在任务完成后进行处理,我建议您将其放在onPostExecute
方法本身中,或者使用从onPostExecute
回调到Activity
。
【讨论】:
我猜你是对的,但你能解释一下吗?任何sn-ps。因为我不确定如何使用 onPostExecute 的回调。谢谢。【参考方案3】:如果我正确理解您的问题,您需要在 ProgressDialog
中更新您的 AsyncTask 的进度,这目前不起作用。所以有几点需要注意:我不确定你想用.get()
实现什么,但我假设你想显示进度。
我在下面修改了您的程序,以根据您的 AsyncTask 的进度更新 UI 线程。每次您需要更新进度时,请在 doInBackground
方法中更新 prog
变量。
public class myAsync extends AsyncTask<String, Integer, List>
String message; // for dialog message
ProgressDialog progress;
Intent myIntent;
Context ctx;
public myAsync(String message, Context ctx)
this.message = message;
this.ctx = ctx;
progress = new ProgressDialog(ctx);
@Override
protected void onPreExecute()
// Runs on the UI thread
progress.setMessage(message);
progress.setIndeterminate(true);
progress.setCancelable(false);
progress.show();
@Override
protected List doInBackground(String... params)
// Runs in the background thread
// publish your progress here!!
int prog = 5; // This number will represent your "progress"
publishProgress(prog);
return anyList;
protected void onProgressUpdate(Integer... progress)
// Runs in the UI thread
// This method will fire (on the UI thread) EVERYTIME publishProgress
// is called.
Log.d(TAG, "Progress is: " +progress);
@Override
protected void onPostExecute(List result)
// Runs in the UI thread
for (int i=0; i<result.size(); i++)
Log.d(TAG, "List item: " + result.get(i));
if(progress.isShowing())
progress.dismiss();
【讨论】:
有了get
,他显然是想从任务中得到结果,以便更新他的界面
@rds 你会在 AsyncTask 的上下文中使用.get
吗?因此,为什么我的假设“我不确定你想用...实现什么”,然后是我对 OP 问题的解释。
@Marvin,首先感谢您的评论。简单地说,我正在从 Web 服务器获取 json。在执行此事务时,只想显示进度对话框窗口,仅此而已。如果我不调用 .get(),那很好。单击按钮后立即显示对话框(按钮将触发异步)。但顺便说一句,我也需要 json 结果。据我所知 .get() 方法返回结果。当我试图获取时,对话窗口在交易过程中显示的时间太短了。我希望现在更容易了。
@OgulcanOrhan 试试其他回答者发布的建议,如果您仍然卡住,我可以尝试帮助您。
@OgulcanOrhan 我对我的答案的onPostExecute
方法进行了小幅编辑,以演示您将如何处理 UI 线程。因此,如果您必须更新 ListView,您可以在 onPostExecute
方法中执行此操作。这就是我认为你正在尝试做的事情。即在执行完成后,获取并做某事你的结果。好吧,do something 部分就是您要放入 onPostExecute
方法中的内容。【参考方案4】:
尝试像这样使用 runOnUiThread:
runOnUiThread(new Runnable()
public void run()
dialog.show();
);
在 AsyncTask 上运行某些东西意味着它会远离 UIthread,所以通常你不能在没有处理程序和我通常远离的东西的情况下从 Async 方法内部运行 ui 操作。我还通过在我的 oncreate 上方的类中创建一个progressDialog 作为变量来处理这样的解决方案,因此它对整个类都是可见的。然后我在我的 asynctask 之前调用 progressdialog,然后因为它对整个班级可见,我在 onPostExecute 中调用 .dissmiss()
【讨论】:
onPreExecute
和 onPostExecute
都在 UI 线程上运行。 doInBackground
是唯一没有的东西。
@JakeWharton 我认为他们只将数据返回到 UI 线程并且不会在其上运行,但我可能是错的.....我还没有完全记住 android 文档的每一行,哈哈
我已经试过了,没用。还是谢谢。以上是关于调用 AsyncTask.get() 时未显示 ProgressDialog [重复]的主要内容,如果未能解决你的问题,请参考以下文章
Android AsyncTask get()形成另一个AsyncTask()