调用 AsyncTask.get() 时未显示 ProgressDialog

发布于 2024-12-29 06:33:56 字数 1687 浏览 1 评论 0原文

可能的重复:
AsyncTask 阻止 UI 威胁并延迟显示进度条 < /p>

我想要在从任何服务器检索 JSON 时显示进度对话框。所以我使用 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();
    }
}

这是 myActivity,它调用 AsyncTask:

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 秒),

这是什么问题?

Possible Duplicate:
AsyncTask block UI threat and show progressbar with delay

I want to show a progressDialog while retrieving JSON from any server. So I had used AsyncTask as a solution (not sure any different way out).

Everything is fine, the ProgressDialog works properly until I call .get() method using AsyncTask instance. I suppose it's blocking UI somehow. Here is my 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();
    }
}

And here is myActivity which is calls AsyncTask:

myAsync asyncTask = new myAsync("Loading...", this);
asyncTask.execute("Any string", "Other string");
asyncTask.get(); // If I comment out this line, ProgressDialog works

After execute, when I tried to log the result from doInBackground and onPostExecute both there is no problem. But if I want to get with .get() the result ProgressDialog is not shown or shown so little time (maybe 0.2 seconds)

What's the problem?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

錯遇了你 2025-01-05 06:33:56

是的,如果需要计算完成,get() 等待,然后检索其结果。这意味着您正在阻塞 UI 线程,等待结果。

解决方案:不要调用get

通常,您会在postExecute中调用函数(回调)。

Yes, get() waits if necessary for the computation to complete, and then retrieves its result. This means, that you are blocking your UI thread, waiting for the result.

Solution: Don't call get

Usually, you will call a function (callback) in the postExecute.

流星番茄 2025-01-05 06:33:56

调用 .get()AsyncTask 更改为有效的“SyncTask”,因为它会导致当前线程(即 UI 线程)等待 AsyncTask已完成处理。由于您现在阻塞了 UI 线程,因此对 ProgressDialog.show() 方法的调用永远不会有机会让对话框在屏幕上自行绘制。

删除该调用将使其能够在后台正常运行。

如果您需要在任务完成后进行处理,我建议您将其放在 onPostExecute 方法本身中,或者使用 onPostExecuteActivity 的回调代码>.

Calling .get() changes your AsyncTask into an effective "SyncTask" as it causes the current thread (which would be the UI thread) to wait until the AsyncTask has finished its processing. Since you are now blocking the UI thread the call to the ProgressDialog's .show() method never gets a chance to allow the dialog to draw itself the screen.

Removing the call will allow it to run properly in the background.

If you need to do processing after the task has completed I suggest you either put it inside the onPostExecute method itself or use a callback to the Activity from onPostExecute.

卸妝后依然美 2025-01-05 06:33:56

如果我正确理解您的问题,您需要在 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();
  }
}

If I understand your question correctly, you need to update the progress of your AsyncTask in a ProgressDialog and this isn't currently working. So a couple of things to note: I'm not sure what you're trying to achieve with .get() but I'll assume you want to display the progress.

I've modified your program below to update the UI thread with your AsyncTask's progress. Everytime you need to update the progress, update that prog variable in the doInBackground method.

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();
  }
}
卷耳 2025-01-05 06:33:56

尝试像这样使用 runOnUiThread :

         runOnUiThread(new Runnable(){
            public void run() {
                dialog.show();
                }});    

在 AsyncTask 上运行某些内容意味着它远离 UIthread,因此通常您无法在没有处理程序和我通常远离的东西的情况下从 Async 方法内部运行 ui 操作。我还通过在 oncreate 之上的类中创建一个 ProgressDialog 作为变量来处理这样的解决方案,以便它对整个类可见。然后,我在异步任务之前调用进度对话框,然后由于它对整个类可见,所以我在 onPostExecute 中调用 .dissmiss()

Try using runOnUiThread like this:

         runOnUiThread(new Runnable(){
            public void run() {
                dialog.show();
                }});    

Running something on a AsyncTask means that its running away from the UIthread so usually you cant run ui operations from inside Async methods without handlers and stuff which I usually stay away from. I also handle such a solution by creating a progressDialog as a variable in my class above my oncreate so its visible to the whole class. I then call the progressdialog right before my asynctask and then since its visible to the whole class I call .dissmiss() in the onPostExecute

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文