How to show progress dialog (in separate thread?) while processing some code in main thread
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();
}
}
精彩评论