简体   繁体   English

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

[英]Showing progress dialog while loading database in Android

I am loading a database without problems in a SQLiteOpenHelper>>onCreate(SQLiteDatabase) method. 我正在使用SQLiteOpenHelper>>onCreate(SQLiteDatabase)方法加载数据库而没有问题。

However, when I try to wrap the loading of the database in an AsyncTask in order to show a progress bar, I keep receiving the message that the database is closed(!). 但是,当我尝试将数据库的负载包装在AsyncTask中以显示进度条时,我不断收到消息说数据库已关闭(!)。 What is the reason of that ? 是什么原因呢?

As an example, this code works fine : 例如,此代码可以正常工作:

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

But if I wrap the same code in a class (indirectly) extending AsyncTask , I will receive the error message saying that the database is closed : 但是,如果我将相同的代码包装在扩展AsyncTask的类中(间接地),则会收到错误消息,指出数据库已关闭:

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

LoadDBTask extends ProgressAsyncTask , that at it turns extends from AsyncTask . LoadDBTask扩展了ProgressAsyncTask ,它又从AsyncTask扩展了。 It wraps the same code than above. 它包装与上面相同的代码。 It also takes care of showing the progress bar. 它还负责显示进度栏。

Here the code for LoadDBTask : 这里是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;  
            } 
    }
}

And for completeness, here the code of ProgressAsyncTask : 为了完整起见,这里是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();
    }
}
}

You haven't shown us where you're closing the db so I'm going to assume you're closing it soon after: 您尚未向我们显示要关闭 db因此我假设您将在不久之后关闭它:

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

Ie in your calling class and this is most likely where your error lies. 即在您的呼叫课程中,这很可能是您的错误所在。 Move the DB closing statement to the onPostExecute method and that should solve your issue. 将数据库关闭语句移至onPostExecute方法,这应该可以解决您的问题。

Of course, you will have to override onPostExecute in LoadDBTask to do this. 当然,您必须重写onPostExecute中的LoadDBTask来执行此操作。 Remember that AsyncTask is asynchronous and as such it will not block at the new LoadDBTask statement I mentioned. 请记住, AsyncTask异步的 ,因此它不会在我提到的new LoadDBTask语句处new LoadDBTask

I would do this: 我会这样做:

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM