简体   繁体   中英

Showing progress dialog while loading database in Android

I am loading a database without problems in a SQLiteOpenHelper>>onCreate(SQLiteDatabase) method.

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(!). 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 :

@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 . It wraps the same code than above. It also takes care of showing the progress bar.

Here the code for 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 :

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:

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.

Of course, you will have to override onPostExecute in LoadDBTask to do this. Remember that AsyncTask is asynchronous and as such it will not block at the new LoadDBTask statement I mentioned.

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

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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