【问题标题】:ProgressDialog doesn't appear when executing a Thread using AsyncTask使用 AsyncTask 执行线程时不会出现 ProgressDialog
【发布时间】:2017-01-29 06:43:48
【问题描述】:

我是 Android 编程的新手,所以希望你能帮助我。我有这个AsyncTask,它通过OnClickListener 事件和doInBackground() 方法执行,是Thread,它不在UI 线程上运行。

AsyncTask通过OnClickListener执行:

Button button = (Button) findViewById(R.id.button);
button.setOnClickListener(new View.OnClickListener() {
  @Override
  public void onClick(View v) {
    new MyAsyncTask().execute();
  }
});

AsyncTaskMainActivity 的子类:

private class MyAsyncTask extends AsyncTask<Void, Void, Void> {

  ProgressDialog progress;

  @Override
  protected void onPreExecute() {
    // Show ProgressDialog before the task starts.
    progress = new ProgressDialog(MainActivity.this);
    progress.setMessage("Running...");
    progress.setCancelable(false);
    progress.show();
  }

  @Override
  protected Void doInBackground(Void... params) {
    // Since the thread is not running on the UI thread,
    // I have to use the runOnUiThread() method so the
    // app won't crash when the thread is complete.
    runOnUiThread(new Runnable() {
      @Override
      public void run() {
        try {
          new ThreadFromOtherClass(arg1, arg2);
        } catch (Exception e) {
          Log.e("Exception", "Something happened.", e);
        }
      }
    });
    return null;
  }

  @Override
  protected void onPostExecute(Void aVoid) {
    // Hide the dialog when the task ends.
    progress.dismiss();
  }
}

我在运行Thread 时没有遇到任何问题,但ProgressDialog 在任务执行期间没有显示。但是,如果我排除 runOnUiThread() 方法,则会出现对话框,但应用程序会在 Thread 完成时崩溃。知道我做错了什么吗?

【问题讨论】:

  • 像这样从doInBackground() 调用runOnUiThread() 完全违背了使用AsyncTask 的目的。崩溃的可能是 UI 更新,您需要将其移至 onPostExecute()
  • @MikeM。是的,但我不知道如何运行Thread 而不会出现任何崩溃问题......
  • @HumblePotatoII,检查我使用构造函数发布的答案。
  • ^ @MikeM。关于你不应该在异步任务中使用 runOnUiThread() 的事实是正确的。如果您需要有关进度对话框的帮助,仍然欢迎在您的应用迷恋时发布日志。
  • @yotamhadas 但是当Thread 完成时,我遇到了应用程序崩溃的问题。还有其他方式/想法吗?

标签: android multithreading android-asynctask


【解决方案1】:

ProgressDialog 没有出现

创建MyAsyncTask的构造函数并传递MainActivtyContext

private class MyAsyncTask extends AsyncTask<Void, Void, Void> {
Context context;

public MyAsyncTask(Context context){
  context.this = context;
}

  ProgressDialog progress;

  @Override
  protected void onPreExecute() {
    // Show ProgressDialog before the task starts.
    progress = new ProgressDialog(context);
    progress.setMessage("Running...");
    progress.setCancelable(false);
    progress.show();
  }

onClick 内部:

new MyAsyncTask(MainActivity.this).execute();

【讨论】:

  • 这究竟是如何解决问题的?也就是说,它与 OP 已有的有什么不同?
  • @MikeM.,我也确定runOnUiThread不能在asynctask内部的dackground进程中使用,但我只是回答了如何显示progressDialog的问题
  • runOnUiThread() 调用是问题所在。不是AsyncTask 如何获得Context。那里运行的线程阻塞了 UI 线程,这就是 ProgressDialog 不显示的原因。请注意 OP 提到它确实在他们删除该呼叫时显示。这不会改变任何事情。
  • @MikeM。我不认为runOnUiThread() 是问题所在。它不会阻塞 UI 线程。他实际上是从那里启动另一个工作线程,它将再次在后台执行。如果我弄错了,请纠正我:)
  • @RobinRex 是的,我说错了。我的真正意思是“那里运行的 code 阻塞了 UI 线程。”我不相信他们的ThreadFromOtherClass 课程实际上是Thread,尽管有这个名字。如果您查看有关该问题的修订,您会发现他们已经发布了一段时间,基本上相当于一个简单的方法,虽然它不是有效的 Java,所以我不想追求它,直到我们有完整、正确的信息。
【解决方案2】:

您的代码可以正常工作。问题在于,您实际上是从 doInBackground() 方法内部启动另一个线程(无论出于何种原因,我都认为这不是一个好主意)。

一旦启动第二个线程,您就会收到对onPostExecute() 的回调。即使“第二个”线程可能有很多工作要做,您的MyAsyncTask 也不会等待它完成。

因此,实际上,您的对话框显示和关闭的速度非常快,以至于您不会在屏幕上注意到它。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2016-08-28
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多