调用 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()

【讨论】:

onPreExecuteonPostExecute 都在 UI 线程上运行。 doInBackground 是唯一没有的东西。 @JakeWharton 我认为他们只将数据返回到 UI 线程并且不会在其上运行,但我可能是错的.....我还没有完全记住 android 文档的每一行,哈哈 我已经试过了,没用。还是谢谢。

以上是关于调用 AsyncTask.get() 时未显示 ProgressDialog [重复]的主要内容,如果未能解决你的问题,请参考以下文章

Android AsyncTask get()形成另一个AsyncTask()

显示关闭时未调用 didRangeBeacons 方法

在 magento 中调用块时未显示类别

当我调用 std::abort() 时未显示 cout

在 viewDidLoad 外部调用方法时未显示相机胶卷中的最后一张图像

Jquery datatable 在从简单的 Web 服务调用 Web 方法时未在表中显示任何数据