开发者

How to show progress dialog (in separate thread?) while processing some code in main thread

I need to do the following: when app is started it runs an activity (splashActivity) which tries to create an DBHelper (SQLiteDatabase) instance which at creation time checks if database is exists and creates one if it doesn't.

In this DB creation process i want to show the ProgressDialog and prevent the main thread to process while DB is not ready.

the 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();
  }
}

the DBHelper class:

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
  }

I tried to make AsyncTask as DBHelper's inner class:

  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();
        }
    }

so the restoreDB() was:

restoreDB() {
      RestoreDBTask task = new RestoreDBTask();
      task.execute();
}

it starts task showing PD but meanwhile the main thread continues and so it crashes cause DB wasn't ready. That means main thread should be suspended while DB is not ready so i tried to sleep/wait/join with no success. Ok. it's not good anyway.

Next time i made call to restoreDBFromFile() from restoreDB() so that async task was used only for PD displaying:

restoreDB() {
  RestoreDBTask task = new RestoreDBTask();
  task.execute();
  restoreDBFromFile();    
}

It doesn't display any PD. So I tried to create PD right in the restoreDB():

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

but no PD either! Next time i tried the following:

    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();
}

once again got no PD and got immediate crash:

04-12 08:40:38.894: ERROR/AndroidRuntime(2448): ERROR: thread attach failed 04-12 08:40:38.913: DEBUG/dalvikvm(2448): LinearAlloc 0x0 used 639500 of 5242880 (12%) 04-12 08:40:39.094: DEBUG/ddm-heap(2454): Got feature list request 04-12 08:40:39.492: WARN/dalvikvm(2454): threadid=15: thread exiting with uncaught exception (group=0x4001b188) 04-12 08:40:39.492: ERROR/AndroidRuntime(2454): Uncaught handler: thread ProgressDialog exiting due to uncaught exception 04-12 08:40:39.504: ERROR/AndroidRuntime(2454): java.lang.RuntimeException: Can't c开发者_如何学Create handler inside thread that has not called Looper.prepare() 04-12 08:40:39.504: ERROR/AndroidRuntime(2454): at android.os.Handler.(Handler.java:121) 04-12 08:40:39.504: ERROR/AndroidRuntime(2454): at android.app.Dialog.(Dialog.java:105) 04-12 08:40:39.504: ERROR/AndroidRuntime(2454): at android.app.AlertDialog.(AlertDialog.java:63) 04-12 08:40:39.504: ERROR/AndroidRuntime(2454): at android.app.ProgressDialog.(ProgressDialog.java:80) 04-12 08:40:39.504: ERROR/AndroidRuntime(2454): at android.app.ProgressDialog.(ProgressDialog.java:76) 04-12 08:40:39.504: ERROR/AndroidRuntime(2454): at android.app.ProgressDialog.show(ProgressDialog.java:101) 04-12 08:40:39.504: ERROR/AndroidRuntime(2454): at 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)

.

Tried a few more things with no result... So I just can't figure out what's wrong.

Once again - I just need to show PD while restoreDB() executing. I can't run restoreDB() in separate thread because I need it finished before app can proceed. As I can see PD should be run in separate thread only but i can't manage it.

Now I have 2 additional questions:

1) If a PD should be created in separate thread could it be created and showed if it's thread doesn't do anything at all. I mean something like this:

    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();

As I understand the thread dies immediately after executing run() cause there is nothing to do and so PD doesn't show.

2) PD by itself doesn't suspend any thread while displaying, does it?


Try to declare AsyncTask as an inner class for the activity, instantiate and execute it there. I think the problem is in context given to ProgressDialog when you are creating it, your logic for doing this is too complicated. Declaring AsyncTask in activity is more common practice.

Then, AsyncTask must do all you need with DB in doInBackground method

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();
    }
}
0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜