【问题标题】:Show ProgressDialog, Retrieve Data, and WAIT FOR IT显示 ProgressDialog、检索数据并等待它
【发布时间】:2011-05-08 03:35:52
【问题描述】:

我正在编写一个应用程序,它在很多时候会尝试从网站检索帐户信息。我想编写一个函数(“getAccount()”)来执行以下操作:

  1. 显示进度对话框
  2. 致电网站
  3. 等待回复
  4. 清除 ProgressDialog
  5. 前四步完成后,将控制权返回给调用函数

我从页面获取数据没有问题;我遇到的问题是整个“显示对话框/等待完成/将控制权返回给调用函数”部分。要么 ProgressDialog 根本不显示,要么函数在从站点发出数据请求后立即返回给调用者,而没有给它足够的时间来检索数据。

任何帮助将不胜感激。

编辑:我在下面添加了一些关于 AsyncTask 的代码。请注意,我在grabURL() 中有MsgBox("done") 行;这只是一个 Toast 调用。当我运行这段代码时,“完成”会在 HTTP 请求仍在进行时弹出。此 MsgBox 行仅存在,因此我可以查看 grabURL 是否正确等待 GrabURL 完成(它不是)。

public void grabURL() {
   new GrabURL().execute();
   MsgBox("done");
}

private class GrabURL extends AsyncTask<String, Void, Void> {
   private ProgressDialog Dialog = new ProgressDialog(MyContext);

   protected void onPreExecute() {
       Dialog.setTitle("Retrieving Account");
       Dialog.setMessage("We're retrieving your account information. Please wait...");
       Dialog.show();
   }

   protected Void doInBackground(String... urls) {
       try {
           // Get account info from the website
           String resp = GetPage(ThePage); // I have this classed out elsewhere
           // Some other code that massages the data
           AccountRetrievalSuccess = true;
       } catch (Exception e) {
           AccountRetrievalSuccess = false;
       }

       return null;
   }

   protected void onPostExecute(Void unused) {
       Dialog.dismiss();
   }

}

【问题讨论】:

标签: java android


【解决方案1】:

显示完成消息框是因为 AsyncTask 正在使用单独的线程来运行 doInBackground。执行的调用不会阻塞。您可以在调用解除后将消息框移至 onPostExecute。小费。您可能想在 onPause 中调用 progress.cancel ,否则您可能会在方向更改时出现不需要的行为。最后,如果您在 doInBackground 中检索信息,请考虑在 doInBackground 中返回信息。该信息将传递给 onPostExecute。因此,如果信息是对象 MyInfo 考虑:

private class GrabURL extends AsyncTask<String, Void, MyInfo> {

【讨论】:

  • 我想要完成的是调用函数 (grabURL) 等到调用函数 (GrabURL) 完成后再返回 - 这就是为什么我有 MsgBox 它所在的位置.我使用 AsyncTask 的唯一真正原因是 ProgressDialog 将正确显示。
  • @Don:grabURL() 不会等待,因为它在 UI 线程上运行,该线程正在显示对话框(理论上已准备好管理任何输入事件)。您必须依靠 onPostExecute() 才能知道任务何时完成。
  • @Don Quixote 不幸的是,时间密集型的阻塞调用在 Android 中效果不佳。您将得到的是可怕的 ANR 无响应对话框。您可以使用 asynchTask 并发布其他人提到的不可取消的进度对话框来获得相同的有效行为。这避免了 ANR 对话框。
【解决方案2】:

如果没有看到一些代码就不能肯定地说,但是当您想要对网站进行同步调用(这将阻止并等待返回数据)时,听起来您正在对网站进行异步调用。

【讨论】:

  • 这正是正在发生的事情;不幸的是,如果不异步调用,我就无法执行 ProgressDialog;如果我在一个线程中运行它,ProgressDialog 不会显示。
【解决方案3】:

您想使用 AsyncTask,在 onPreExecute 中生成用户不可取消的 ProgressDialog,在 doInBackground 中完成您的工作,并在 onPostExecute 中将其关闭。

类似这样的:

public class MyApp extends Activity
{

  @Override
  public void onCreate(Bundle savedInstanceState)
  {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.main);

    // blah blah blah

    URL url;
    try
    {
      url = new URL("http://example.com");
      new MyTask().execute(url);
    }
    catch (MalformedURLException e)
    {
    }

  }

  protected void doSomeStuff()
  {
    // stuff to do after the asynctask is done
  }


  protected void throwAWobbly()
  {
    // stuff to do if you didn't get the data
  }

  // inner class to do the data getting off the UI thread,
  // so android doesn't "not responding" kill you
  private class MyTask extends AsyncTask<URL, Void, Boolean>
  {
    private ProgressDialog dialog;
    private boolean gotData = false;

    protected void onPreExecute()
    {
      // create a progress dialog
      dialog = ProgressDialog.show(MyApp.this, "",
                "Doing stuff. Please wait...", false, false);
    }

    protected Boolean doInBackground(URL... urls)
    {
       // get your data in here!
       return gotData;
    }

    protected void onPostExecute(Boolean result)
    {
       // get rid of the progress dialog
       dialog.dismiss();

       if (true == result)
       {
         // got all data!
         doSomeStuff();
       }
       else
       {
         // oops!
         throwAWobbly();
       }
    }
  }

}

【讨论】:

  • 我试过了,但几乎没有成功。用上面的代码查看我的编辑。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2021-05-20
  • 2013-04-05
  • 1970-01-01
  • 2013-12-02
  • 1970-01-01
  • 2016-02-21
  • 1970-01-01
相关资源
最近更新 更多