在Android中加载数据库时显示进度对话框

时间:2012-01-21 14:48:21

标签: android

我在SQLiteOpenHelper>>onCreate(SQLiteDatabase)方法中加载数据库没有问题。

但是,当我尝试将数据库的加载包装在AsyncTask中以显示进度条时,我一直收到数据库已关闭的消息(!)。这是什么原因?

例如,此代码可以正常工作:

@Override
public void onCreate(SQLiteDatabase db) { 
    ...
    String sqlStatement = ... //content of file with sql
    for (String sqlStatement : sqlCode.split(";")) {
        db.execSQL(sqlStatement);
    }
}

但是如果我在类(间接)扩展AsyncTask中包含相同的代码,我将收到错误消息,指出数据库已关闭:

@Override
public void onCreate(SQLiteDatabase db) { 
    new LoadDBTask(context, db, progressDialog, alertDialog).execute(new Integer[] {scriptId});
}

LoadDBTask扩展ProgressAsyncTask,它从AsyncTask开始延伸。它包含与上面相同的代码。它还负责显示进度条。

此处为LoadDBTask的代码:

public class LoadDBTask extends ProgressAsyncTask<Integer> {

    protected Context context;
    protected SQLiteDatabase db;

    public LoadDBTask(Context context, SQLiteDatabase db, ProgressDialog progressDialog, AlertDialog alertDialog) {
        super(progressDialog, alertDialog);
        this.context = context;
        this.db = db;
    }

    public boolean loadScript(String sqlCode) {
        for (String sqlStatement : sqlCode.split(";")) {
            sqlStatement = sqlStatement.trim();
            if(!sqlStatement.isEmpty()) {
                try {
                    db.execSQL(sqlStatement);
                } catch (Exception e) {  
                    Log.e(getClass().getSimpleName(), "Problem executing SQL statement: "+sqlStatement,e);
                    return false;
                }
            }   
        }
        return true;
    }

    @Override
    protected Boolean doInBackground(Integer... params) {
            int scriptId = params[0];
            String sqlCode;
            try {
                sqlCode = ResourceUtil.getFileContent(context.getResources(), scriptId);
                return loadScript(sqlCode);
            } catch (IOException e) {
                Log.e(getClass().getSimpleName(), "Error reading script file: ",e);
                return false;  
            } 
    }
}

为了完整起见,这里的代码为ProgressAsyncTask

public abstract class ProgressAsyncTask<Params> extends AsyncTask<Params, Integer, Boolean> {

protected ProgressDialog progressDialog;
protected AlertDialog alertDialog;

public ProgressAsyncTask(ProgressDialog progressDialog, AlertDialog alertDialog) {
    this.progressDialog = progressDialog;
    this.alertDialog = alertDialog;
}


@Override
protected void onProgressUpdate(Integer... changed) {
    if(progressDialog != null)
        progressDialog.setProgress(changed[0]);

}

@Override
protected void onPreExecute() {
    if(progressDialog != null)
        progressDialog.show();
}

@Override
protected void onPostExecute(Boolean result) {
    if(progressDialog.isShowing())
        progressDialog.dismiss();
    if(!result) {
        if(alertDialog != null)
            alertDialog.show();
    }
}
}

2 个答案:

答案 0 :(得分:1)

您还没有向我们展示您关闭 db的位置,所以我假设您很快就会关闭它:

new LoadDBTask(context, db, progressDialog, alertDialog).execute
  (new Integer[] {scriptId});

即。在调用类中,这很可能是您的错误所在。将DB结束语句移动到onPostExecute方法,这应解决您的问题。

当然,您必须覆盖onPostExecute中的LoadDBTask才能执行此操作。请注意AsyncTask 异步,因此在我提到的new LoadDBTask声明中 阻止

答案 1 :(得分:0)

我会这样做:

private ProgressDialog progressDialog;
private Handler handler;

public yourConstructor(Context context){
    progressDialog = new ProgressDialog(context);
    progressDialog.setMessage("wait");
    progressDialog.setCancelable(true);
    handler = new Handler();
}

@Override
public void onCreate(SQLiteDatabase db) { 
    progressDialog.show();
    new Thread(new Runnable() {
        @Override
        public void run() {

            //your bd access here

            handler.post(new Runnable() {
                @Override
                public void run() {
                    progressDialog.cancel();
                }
            );
        }
    }).start();
}