如何在主线程中处理一些代码时显示进度对话框(在单独的线程中?)

Sta*_*tan 2 android progressdialog android-asynctask


我需要执行以下操作:当app启动时,它会运行一个活动(splashActivity),它尝试创建一个DBHelper(SQLiteDatabase)实例,该实例在创建时检查数据库是否存在,如果不存在则创建一个.
在这个数据库创建过程中,我想显示ProgressDialog并防止主线程在DB未就绪时进行处理.

splashActivity:

public class SplashActivity extends Activity {
    /** Called when the activity is first created. */
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.splash);
        showSplash();
        DBHelper dbHelper = new DBHelper(this);
        dbHelper.close();
  }
}
Run Code Online (Sandbox Code Playgroud)

DBHelper类:

public class DBHelper extends SQLiteOpenHelper { 
...
    private ProgressDialog mProgressDialog;
...
  public DBHelper(Context context) { 
    super(context, DB_NAME, null, 1);
    appContext=context;
    dbReadable = getReadableDatabase();
    if (createDB)
        initDB();
  } 
  @Override 
  public void onCreate(SQLiteDatabase db) {
      createDB=true;
  } 
  public void initDB() {
      ...
      if (createDB) 
          restoreDB();
      ...
  }

  private void restoreDB(){
   // place for db creation/restoring method call (restoreDBFromFile() etc)
   // and displaying the progress
  }
Run Code Online (Sandbox Code Playgroud)

我试图将AsyncTask作为DBHelper的内部类:

  private class RestoreDBTask extends AsyncTask <Void, Void, String>
    {
        private ProgressDialog dialog;

        @Override
        protected void onPreExecute()
        {
            this.dialog = ProgressDialog.show(DBHelper.this.appContext, DBHelper.this.appContext.getResources().getString(R.string.progress_wait), 
                    DBHelper.this.appContext.getResources().getString(R.string.progress_db_installing), true);
        }

        @Override
        protected String doInBackground(Void... params)
        {
            restoreDBFromFile();
            return "";
        }

        @Override
        protected void onPostExecute(String result)
        {
            this.dialog.dismiss();
        }
    }
Run Code Online (Sandbox Code Playgroud)

所以restoreDB()是:

restoreDB() {
      RestoreDBTask task = new RestoreDBTask();
      task.execute();
}
Run Code Online (Sandbox Code Playgroud)

它开始显示PD的任务,但同时主线程继续,因此它崩溃导致DB没有准备好.这意味着主要线程应该暂停,而DB没有准备好所以我试图睡眠/等待/加入没有成功.好.反正它不好.
下次我从restoreDB()调用restoreDBFromFile(),以便异步任务仅用于PD显示:

restoreDB() {
  RestoreDBTask task = new RestoreDBTask();
  task.execute();
  restoreDBFromFile();    
}
Run Code Online (Sandbox Code Playgroud)

它不显示任何PD.所以我尝试在restoreDB()中创建PD:

restoreDB() {
   mProgressDialog = ProgressDialog.show(appContext, 
          appContext.getResources().getString(R.string.progress_wait), 
          appContext.getResources().getString(R.string.progress_db_installing), 
          true);
  restoreDBFromFile();    
}
Run Code Online (Sandbox Code Playgroud)

但也没有PD!下次我尝试以下内容:

    restoreDB() {
      Thread thread =  new Thread(null, new Runnable(){
              @Override
              public void run() {
                  mProgressDialog = ProgressDialog.show(appContext, 
                          appContext.getResources().getString(R.string.progress_wait), 
                          appContext.getResources().getString(R.string.progress_db_installing), 
                          true);
              }
          }, "ProgressDialog");
      thread.start();
      restoreDBFromFile();
}
Run Code Online (Sandbox Code Playgroud)

再次没有PD并立即崩溃:

04-12 08:40:38.894:ERROR/AndroidRuntime(2448):ERROR:线程附加失败04-12 08:40:38.913:DEBUG/dalvikvm(2448):LinearAlloc 0x0使用639500的5242880(12%)04-12 08:40:39.094:DEBUG/ddm-heap(2454):获得功能列表请求04-12 08:40:39.492:WARN/dalvikvm(2454):threadid = 15:线程退出未捕获异常(组= 0x4001b188)04 -12 08:40:39.492:ERROR/AndroidRuntime(2454):未捕获处理程序:线程ProgressDialog由于未捕获异常退出04-12 08:40:39.504:ERROR/AndroidRuntime(2454):java.lang.RuntimeException:不能在没有调用Looper.prepare()的线程内创建处理程序04-12 08:40:39.504:ERROR/AndroidRuntime(2454):在android.os.Handler.(Handler.java:121)04-12 08:40: 39.504:ERROR/AndroidRuntime(2454):在android.app.Dialog.(Dialog.java:105)04-12 08:40:39.504:ERROR/AndroidRuntime(2454):在android.app.AlertDialog.(AlertDialog.java :63)04-12 08:40:39.504:ERROR/AndroidRuntime(2454):在android.app.ProgressDialog.(ProgressDialog.java:80)04-12 08:40 :39.504:ERROR/AndroidRuntime(2454):在android.app.ProgressDialog.(ProgressDialog.java:76)04-12 08:40:39.504:ERROR/AndroidRuntime(2454):在android.app.ProgressDialog.show(ProgressDialog) .java:101)04-12 08:40:39.504:ERROR/AndroidRuntime(2454):在android.app.ProgressDialog.show(ProgressDialog.java:90)04-12 08:40:39.504:ERROR/AndroidRuntime(2454 ):at com.taxiorder.DBHelper $ 1.run(DBHelper.java:157)04-12 08:40:39.504:ERROR/AndroidRuntime(2454):at java.lang.Thread.run(Thread.java:1096)

.
尝试了一些没有结果的事情......所以我无法弄清楚出了什么问题.

再一次 - 我只需要在restoreDB()执行时显示PD.我不能在单独的线程中运行restoreDB(),因为我需要在app继续之前完成它.我可以看到PD应该只在单独的线程中运行,但我无法管理它.

现在我还有两个问题:

1)如果PD应该在单独的线程中创建,那么它是否可以创建并显示它的线程是否完全没有做任何事情.我的意思是这样的:

    new Thread(){
          public void run(){
              mProgressDialog = ProgressDialog.show(appContext, 
                      appContext.getResources().getString(R.string.progress_wait), 
                      appContext.getResources().getString(R.string.progress_db_installing), 
                      true);

      }.start();
Run Code Online (Sandbox Code Playgroud)

据我所知,线程在执行run()后立即死亡,导致无事可做,因此PD不会显示.
2)PD本身在显示时不会暂停任何线程,是吗?

Ole*_*gas 5

尝试声明AsyncTask为活动的内部类,在那里实例化并执行它.我认为问题出在上下文中,ProgressDialog当你创建它时,你做这个的逻辑太复杂了.宣布AsyncTask活动是更常见的做法.

然后,AsyncTask必须在doInBackground方法中使用DB完成所需的一切

public class SplashActivity extends Activity {
    /** Called when the activity is first created. */
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.splash);

        new RestoreDBTask().execute();
    }

}

private class RestoreDBTask extends AsyncTask <Void, Void, String>
{
    private ProgressDialog dialog;

    @Override
    protected void onPreExecute()
    {
        dialog = ProgressDialog.show(
            SplashActivity.this,
            getString(R.string.progress_wait),
            getString(R.string.progress_db_installing), 
            true);
    }

    @Override
    protected String doInBackground(Void... params)
    {
        // do all the things with DB
        DBHelper dbHelper = new DBHelper(SplashActivity.this);
        dbHelper.close();
        return "";
    }

    @Override
    protected void onPostExecute(String result)
    {
        dialog.dismiss();
    }
}
Run Code Online (Sandbox Code Playgroud)