【问题标题】:SQLite database never close in my Android appSQLite 数据库永远不会在我的 Android 应用程序中关闭
【发布时间】:2012-03-09 15:46:00
【问题描述】:

我的 Android 应用程序有问题。我正在使用下面的代码在 AsyncTask 中打开 SQLite 数据库。一切正常,但是当我尝试在 onStop()onDestroy 方法中关闭数据库时,它永远不会关闭。

创建和打开数据库的代码:

公共类 SQLiteDB 扩展 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;

}

AssyncTask 类:

公共类 OpenDatabaseTask 扩展 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");
}

}

和活动(仅重要部分):

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

所以当我尝试使用close() 方法关闭数据库时,sqliteDatabase 始终为空,并且数据库永远不会关闭。所以数据库仍然处于打开状态,调用onDestroy后出现异常。

谢谢你的时间,对不起我的英语,我是捷克人:)

【问题讨论】:

  • 你确定 onStop 被调用了吗?
  • 你确定这是个问题吗?

标签: android sqlite sqlexception


【解决方案1】:

只是一个猜测(假设你想关闭销毁)

在调用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
}

注意:

假设数据库仅存在并且在活动可见时处于打开状态,您应该在 onResume() 中打开数据库并在 onPause() 中关闭它。

如果在代码加载到内存时应该打开数据库,则在 onCreate 中创建它并在 onDestroy 中关闭它

在您的示例中,您在 onCreate 中打开它并在 onStop 中关闭它。 问题:当活动第二次可见时,数据库关闭。 有关详细信息,请参阅 android activity documentation 并在按钮处查看应用程序生命周期。

【讨论】:

    【解决方案2】:

    我有一个具有大量数据库交互的应用程序。我没有用户助手。我的数据库在 UI 线程和后台线程中打开了很多次,但从未关闭过。到目前为止没有任何问题,不知道这是否是正确的做法......

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-11-04
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-09-21
      相关资源
      最近更新 更多