【问题标题】:Displaying a ProgressDialog while waiting for a joined Thread在等待加入的线程时显示 ProgressDialog
【发布时间】:2013-07-08 13:22:14
【问题描述】:

在我的 Activity 中,我从数据库加载列表的内容,并希望在加载时显示 ProgressDialog。
我自己都在工作,但是如果我在线程中加载数据(我应该这样做吗?),列表会在加载数据之前显示。但如果我使用加入,ProgressDialog 甚至不会出现。

我该如何组合呢?或者这对于线程来说根本不可能? (也许是 AsyncTask?)

以下代码供参考:

    final ProgressDialog progressD=ProgressDialog.show(ShopSwitchActivity.this, "", "Loading..", true);

    Thread myThread = new Thread(new Runnable() {  
        @Override
        public void run() {
          try
          {
              getData();
          }catch(Exception e){}
        }
    });
    myThread.start();

    try {
            myThread.join();
    } catch (InterruptedException e) {
    }
    progressD.dismiss();

编辑:使用 AsyncTask 更新代码:

public class LoadList extends AsyncTask<String, Void, Boolean> {

    ProgressDialog dialog;
    ShopSwitchActivity activity;

    public LoadList(ShopSwitchActivity activity) {
        this.activity = activity;
        dialog = new ProgressDialog(activity);
    }

    protected void onPreExecute() {
        this.dialog.setMessage("Loading...");
        this.dialog.show();
    }

        @Override
    protected void onPostExecute(final Boolean success) {
        if (dialog.isShowing()) {
            dialog.dismiss();
        }
    }

    protected Boolean doInBackground(final String... args) {
        try{
       activity.getData();
        } catch (Exception e) {
            Log.e("error", e.getMessage());
        }
       return true;
    }
}

编辑:我的解决方案 现在使用 AsyncTask 加载数据,完成后,我用新数据刷新列表。

【问题讨论】:

标签: android multithreading progressdialog


【解决方案1】:

您可以使用 AsyncTask 来完成。在您想要执行操作的主类中编写 AsyncTask 类。您可以在异步类的 preexcecute 中创建进度对话框,并在异步类的 onpostexecute 中关闭。以下是您将如何执行此操作:

  class MyAsync extends AsyncTask<String, Void, Void> {
     ProgressDialog pd;
     Context co;
     MyActivity ma;

     public MyAsync (MyActivity ma){
         this.ma= ma;
         this.co = ma;
         pd= new ProgressDialog(co);
     }

     @Override
     protected void onPreExecute() {
         this.pd.show();

     super.onPreExecute();
     }
            @Override
            protected Void doInBackground(String... params) {
                // do your database operations here
                return null;
            }

            @Override
            protected void onPostExecute(Void result) {
                // show db results and dismiss progress dialog pd.dismiss();
                super.onPostExecute(result);
            }
        }

在 MyActivity 调用中:

MyActivity ma = this;
new MyAsync(ma).execute();

【讨论】:

  • 尝试使用 AsyncTask,请参阅我的问题中的已编辑代码。但不起作用:“只有创建视图层次结构的原始线程才能触及它的视图”
  • 我编辑了我的答案并对其进行了测试。现在它按预期工作。小错误见谅
  • this.ma= ma; this.co = ma; pd= new ProgressDialog(co); 为什么不只是pd = new ProgressDialog(ma);
  • 它获取上下文这只是我将上下文值用于进度对话框的习惯。这正在按照您希望的方式工作,我对其进行了测试,希望您觉得这很有用。
  • 唯一的问题是,就像我说的那样,我需要在 Main/UI-Thread 中等待直到此任务完成,而不阻塞 ProgressDialog。
【解决方案2】:

你似乎错过了一个线程的重点。线程与您的应用程序同时发生。所以你的应用程序不会调用 start 然后等待线程结束 - 如果它这样做了你可以只使用一个函数。相反,您的代码会继续运行。因此,如果您只是立即调用 join,则您什么也做不了。您可以通过这种方式绕过 NetworkOnMainThreadException,但您仍然会阻止 UI 线程,从而使您的应用程序完全无响应(因此不会显示对话框),并且当看门狗计时器杀死您时,您最终会崩溃.

相反,处理此问题的最佳方法是使用 AsyncTask。在 doInBackground() 中调用 getData。然后关闭 onPostExecute 中的对话框。

【讨论】:

  • 我知道为什么以及如何使用线程,但是我不能在没有线程的情况下使用 ProgressDialog,这是我想使用它的唯一原因。
  • 您可以使用没有线程的进度对话框。你可以使用异步任务(这是一个具有一些内置功能的线程,用于在 UI 线程上进行后线程处理),或者根本不使用任何类型的线程——只需将一个线程放在那里。为什么你认为你需要一个线程?
  • 另外,如果我没有说清楚 - 通过立即调用 join 你永远不会得到绘制进度对话框的实际绘图代码。这一切都发生在 UI 线程上。
  • 我读过的所有教程(关于 ProgressDialogs)都使用了线程/异步,其中大多数(甚至全部)都说我确实需要一个。另外,我不想在没有任何反馈的情况下阻塞 UI 线程几秒钟,如果加载在前台运行,那就是发生了什么。
  • ProgressDialog 只是一个 UI 元素。你可以随时放一个。现在使用线程/异步任务(尤其是 AsyncTasks)通常更容易,但只要您在 UI 线程上,就没有什么能阻止您显示 UI 元素。要么你误读了教程,要么它们大错特错。
【解决方案3】:

实际上你应该使用AsyncTask

Here 是库的链接。这很简单:

1) onPreExecute() = 显示ProgressDialog

2) doInBackground() = 执行你的代码

3) onPostExecute() = 关闭 ProgressDialog

Here 也是一个不错的教程。

一般:

@Override
protected void onPreExecute() {
    dialog = new ProgressDialog(this.context);
    dialog.setMessage("Loading...");
    dialog.setCanceledOnTouchOutside(false);
}

@Override
protected void onPostExecute(String result) {
    if(dialog.isShowing()) {
        dialog.dismiss();
    }
}

【讨论】:

    【解决方案4】:
    private Thread myThread;
    private ProgressDialog mProgDialog;
    
    mProgDialog = ProgressDialog.show(ShopSwitchActivity.this,"","Laden..", true);
    
    myThread= new Thread(new Runnable() 
    {
        public void run() 
        {
        myThread.setPriority(Thread.MIN_PRIORITY);
    
        try
        {
            getData();
        }catch(Exception e){}
    
        runOnUiThread(new Runnable() 
        {
            public void run() 
            {
            if (mProgDialog != null&& mProgDialog.isShowing())
            mProgDialog.dismiss();
            }                                                                               }
        });
    
        }
    });
    myThread.start();
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2013-07-24
      • 2013-11-30
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-11-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多