La base de datos SQLite nunca se cierra en mi aplicación de Android

Tengo un problema con mi aplicación de Android. Estoy usando el código a continuación para abrir la base de datos SQLite en AsyncTask. Todo funciona bien, pero cuando intento cerrar la base de datos en onStop() or onDestroy método, nunca está cerrado.

Código para crear y abrir la base de datos:

la clase pública SQLiteDB extiende SQLiteOpenHelper {

private final Context context;  
private SQLiteDatabase sqliteDatabase = null;

public SQLiteDB(Context context, String DBName) {
    super(context, DBConstant.DB_NAME, null, context.getResources().getInteger(ppredota.android.navigation.view.activities.R.string.database_version));
    this.context = context;
}

public void createDB() throws IOException{


    if(existDB()){
        this.getReadableDatabase();
        this.close();
    }
    else {
        this.getWritableDatabase();
        try {
            copyDB();
            this.close();   
        }
        catch (Exception e) {
            throw new Error("Chyba pri kopirovani databaze");
        }
    }
}
private boolean existDB() {

    SQLiteDatabase checkDatabase = null;

    try{
        String fullPath = DBConstant.DB_PATH + DBConstant.DB_NAME;
        checkDatabase = SQLiteDatabase.openDatabase(fullPath, null, SQLiteDatabase.OPEN_READWRITE);
    }
    catch (SQLiteException sqle) {
        Log.i("existDB()", "Databaze nelze otevrit, neexistuje");
    }
    if(checkDatabase == null){
        Log.i("existDB", "Databaze jeste neexistuje...");
        return false;
    }
    else{
        Log.i("existDB", "Databaze uz existuje...");
        checkDatabase.close();
        return true;
    }

}

private void copyDB() throws IOException {

    InputStream inDBStream = context.getAssets().open(DBConstant.DB_NAME);
    String newDBPath = DBConstant.DB_PATH + DBConstant.DB_NAME;

    OutputStream outDBStream = new FileOutputStream(newDBPath);
    Log.i("copyDB", "Otevren outputstream s cestou k nove databazi");

    byte[] buffer = new byte[1024];
    int length;
    while ((length = inDBStream.read(buffer))>0){
        outDBStream.write(buffer, 0, length);
    }

    outDBStream.flush();
    outDBStream.close();
    inDBStream.close();
}

public void openDB() throws SQLException {
    String fullPath = DBConstant.DB_PATH + DBConstant.DB_NAME;
    if(sqliteDatabase!=null){
        if(sqliteDatabase.isOpen()){
            Log.i("openDB()", "Databaze je jiz otevrena");
        }
        else{
            sqliteDatabase = SQLiteDatabase.openDatabase(fullPath, null, SQLiteDatabase.OPEN_READONLY);
            Log.i("openDB()", "Databaze" + sqliteDatabase.getPath() + "otevrena");
        }
    }
    else{
        sqliteDatabase = SQLiteDatabase.openDatabase(fullPath, null, SQLiteDatabase.OPEN_READONLY);
        if(sqliteDatabase.isOpen()){
            Log.i("openDB()", "Databaze otevrena");
        }

    }
}
@Override
public void close() {

    if(sqliteDatabase!=null){
        sqliteDatabase.close();
        Log.i("close()", "Databaze zavrena");
    }
    super.close();

}

public SQLiteDatabase getSQLiteDatabase() {
    if(sqliteDatabase==null){
        Log.i("getSQLiteDatabase()","Problem, vraci sqliteDatabase = null");
    }
    else{
        Log.i("getSQLiteDatabase()","instance sqliteDatabase vracena bez problemu");
    }

    return sqliteDatabase;

}

Clase AssyncTask:

La clase pública OpenDatabaseTask extiende AsyncTask {

private Context context;
private SQLiteDB sqliteDB;

public OpenDatabaseTask(Context context,SQLiteDB sqliteDB) {
    this.context = context;
    this.sqliteDB = sqliteDB;
}
@Override
protected Void doInBackground(Void... params) {
    publishProgress();

    try {
        sqliteDB.createDB();
    } catch (IOException e) {
        e.printStackTrace();
    }
    sqliteDB.openDB();

    return null;
}
@Override
protected void onProgressUpdate(Void...unused){
    Log.i(OpenDatabaseTask.class.toString(), "Spusteno vlakno");
}

}

y Actividad (solo parte importante):

    private SQLiteDB sqliteDB;
    private SQLiteData sqliteData;
    private OpenDatabaseTask openDatabaseTask;

 @Override
 public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.navigatemenu);

        sqliteDB = new SQLiteDB(getApplicationContext(), sourceDatabaseName);
        openDatabaseTask = new OpenDatabaseTask(getApplicationContext(), sqliteDB);
        openDatabaseTask.execute();

    protected void onDestroy(){
        super.onDestroy();
        Log.i("onDestroy()", "Pokus o zavreni databaze");
            //here is the problem, database never closed
        sqliteDB.close();
    }
    protected void onStop(){
        super.onStop();
        Log.i("onStop()", "Pokus o zavreni databaze");
            //here is the problem, database never closed
        sqliteDB.close();
    }
    protected void onPause(){
        super.onPause();
    }
    protected void onResume(){
        super.onResume();
        //Log.i("onResume()", "Pokus o otevreni databaze");
    }
}

Entonces, cuando intento usar un close() método para cerrar la base de datos, sqliteDatabase siempre es nulo y la base de datos nunca se cierra. Entonces la base de datos todavía está abierta y después de llamar onDestroy ocurre una excepción.

Gracias por tu tiempo y perdón por mi inglés, soy checo :)

preguntado el 09 de marzo de 12 a las 15:03

¿Y estás seguro de que se está llamando a onStop? -

¿Estás seguro de que eso es un problema? -

2 Respuestas

Solo una suposición (suponiendo que quieras cerrar en destruir)

cerrar la base de datos antes de llamar al super

protected void onDestroy(){
    // close befor super is called
    sqliteDB.close();

    super.onDestroy();
    Log.i("onDestroy()", "Pokus o zavreni databaze");
    // sqliteDB.close(); // super.onDestroy may already has destroyed the DB
}

Nota:

Suponiendo que la base de datos solo existe y está abierta mientras la actividad es visible, debe abrir la base de datos en onResume () y cerrarla en onPause ().

Si la base de datos debe estar abierta cuando el código se carga en la memoria, créelo en onCreate y ciérrelo en onDestroy

En su ejemplo, lo abre en onCreate y lo cierra en onStop. Problema: cuando la actividad se vuelve visible por segunda vez, la base de datos se cierra. Para obtener más detalles, consulte documentación de la actividad de Android y observe el ciclo de vida de la aplicación en el botón.

respondido 09 mar '12, 16:03

Tengo una aplicación con mucha interacción con db. Yo no ayudaba al usuario. Mi base de datos se abre muchas veces, en el hilo de la interfaz de usuario y también en el hilo de fondo, pero nunca se cierra. No he tenido problemas hasta ahora, no sé si es la forma correcta de hacerlo ...

contestado el 26 de mayo de 15 a las 19:05

No es la respuesta que estás buscando? Examinar otras preguntas etiquetadas or haz tu propia pregunta.