我需要执行以下操作:当应用程序启动时,它会运行一个活动(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();
}
}
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
}
我试图将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();
}
}
所以restoreDB()是:
restoreDB() {
RestoreDBTask task = new RestoreDBTask();
task.execute();
}
它启动显示PD的任务,但同时主线程继续,因此崩溃导致DB未准备好。这意味着主要线程应该暂停,而DB没有准备好所以我试图睡眠/等待/加入没有成功。好。反正它也不好 下次我从restoreDB()调用restoreDBFromFile(),以便异步任务仅用于PD显示:
restoreDB() {
RestoreDBTask task = new RestoreDBTask();
task.execute();
restoreDBFromFile();
}
它不显示任何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();
}
但也没有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();
}
再次没有PD而立即崩溃:
04-12 08:40:38.894: 错误/ AndroidRuntime(2448):错误: 线程附加失败04-12 08:40:38.913:DEBUG / dalvikvm(2448): LinearAlloc 0x0使用5239880的639500 (12%)04-12 08:40:39.094: DEBUG / ddm-heap(2454):获得了功能列表 要求04-12 08:40:39.492: WARN / dalvikvm(2454):threadid = 15: 线程退出与未捕获的异常 (group = 0x4001b188)04-12 08:40:39.492: 错误/ AndroidRuntime(2454):未捕获 handler:线程ProgressDialog退出 由于04-12未被捕获的例外 08:40:39.504: ERROR / AndroidRuntime(2454): java.lang.RuntimeException:不能 在具有的线程内创建处理程序 不叫做Looper.prepare()04-12 08:40:39.504: 错误/ AndroidRuntime(2454):at android.os.Handler。(Handler.java:121) 04-12 08:40:39.504: 错误/ AndroidRuntime(2454):at android.app.Dialog。(Dialog.java:105) 04-12 08:40:39.504: 错误/ AndroidRuntime(2454):at android.app.AlertDialog。(AlertDialog.java:63) 04-12 08:40:39.504: 错误/ AndroidRuntime(2454):at android.app.ProgressDialog。(ProgressDialog.java:80) 04-12 08:40:39.504: 错误/ AndroidRuntime(2454):at android.app.ProgressDialog。(ProgressDialog.java:76) 04-12 08:40:39.504: 错误/ AndroidRuntime(2454):at android.app.ProgressDialog.show(ProgressDialog.java:101) 04-12 08:40:39.504: 错误/ AndroidRuntime(2454):at android.app.ProgressDialog.show(ProgressDialog.java:90) 04-12 08:40:39.504: 错误/ AndroidRuntime(2454):at com.taxiorder.DBHelper $ 1.run(DBHelper.java:157) 04-12 08:40:39.504: 错误/ 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()后立即死亡导致无事可做,因此PD不会显示 2)PD本身在显示时不会挂起任何线程,是吗?
答案 0 :(得分:5)
尝试将AsyncTask
声明为活动的内部类,在那里实例化并执行它。我认为问题出在ProgressDialog
创建它的上下文中,这样做的逻辑太复杂了。在活动中声明AsyncTask
是更常见的做法。
然后,AsyncTask必须在doInBackground
方法
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();
}
}