Android SQLite DB Когда закрыть

Я работаю с базой данных SQLite на Android. Мой менеджер баз данных является одноэлементным и теперь открывает соединение с базой данных при ее инициализации. Можно ли оставить базу данных открытой все время, чтобы когда кто-то вызывал мой класс для работы с базой данных, он уже открыт? Или я должен открыть и закрыть базу данных до и после каждого доступа. Есть ли какой-либо вред, если просто оставить его открытым все время?

Спасибо!

Ответ 1

i будет держать его открытым все время и закрывать его в каком-то жизненном цикле, например onStop или onDestroy. Таким образом, вы можете легко проверить, используется ли база данных уже при вызове isDbLockedByCurrentThread или isDbLockedByOtherThreads на одном объекте SQLiteDatabase каждый раз, прежде чем использовать его. это предотвратит множественные манипуляции с базой данных и сохранит ваше приложение от потенциального сбоя.

поэтому в вашем singleton у вас может быть такой метод, чтобы получить ваш единственный объект SQLiteOpenHelper:

private SQLiteDatabase db;
private MyDBOpenHelper mySingletonHelperField;
public MyDBOpenHelper getDbHelper() {
    db = mySingletonHelperField.getDatabase();//returns the already created database object in my MyDBOpenHelper class(which extends `SQLiteOpenHelper`)
    while(db.isDbLockedByCurrentThread() || db.isDbLockedByOtherThreads()) {
        //db is locked, keep looping
    }
    return mySingletonHelperField;
}

поэтому всякий раз, когда вы хотите использовать свой открытый вспомогательный объект, вызовите этот метод getter (убедитесь, что он заштрихован)

другой метод в вашем singleton может быть (называемый КАЖДОЕ ВРЕМЯ, прежде чем пытаться вызвать геттер выше):

public void setDbHelper(MyDBOpenHelper mySingletonHelperField) {
    if(null == this.mySingletonHelperField) {
        this.mySingletonHelperField = mySingletonHelperField;
        this.mySingletonHelperField.setDb(this.mySingletonHelperField.getWritableDatabase());//creates and sets the database object in the MyDBOpenHelper class
    }
}

вы можете также закрыть базу данных в синглете:

public void finalize() throws Throwable {
    if(null != mySingletonHelperField)
        mySingletonHelperField.close();
    if(null != db)
        db.close();
    super.finalize();
}

если пользователи вашего приложения могут быстро создавать много взаимодействий с базами данных, вы должны использовать что-то вроде того, что я продемонстрировал выше. но если есть минимальные взаимодействия с базами данных, я бы не стал беспокоиться об этом и просто создавал и закрывал базу данных каждый раз.

Ответ 2

В настоящее время нет необходимости проверять, заблокирована ли база данных другим потоком. Хотя вы используете singleton SQLiteOpenHelper в каждом потоке, вы в безопасности. Из документации isDbLockedByCurrentThread:

Название этого метода происходит с момента, когда активен соединение с базой данных означало, что поток блокировка базы данных. В настоящее время больше нет истинной "базы данных" lock ", хотя потоки могут блокироваться, если они не могут получить базу данных соединение для выполнения конкретной операции.

isDbLockedByOtherThreads устарел с уровня API 16.

Ответ 3

Относительно вопросов:

Мой менеджер баз данных является одноточечным и теперь открывает соединение с базой данных при его инициализации.

Мы должны разделить "открытие DB", "открытие соединения". SQLiteOpenHelper.getWritableDatabase() предоставляет открытую БД. Но нам не нужно контролировать соединения, как это делается внутри.

Можно ли оставить базу данных открытой все время, чтобы когда кто-то звонил моему классу работать с базой данных, он уже открыт?

Да, это так. Соединения не зависают, если транзакции должным образом закрыты. Обратите внимание, что ваша БД также будет автоматически закрыта, если GC завершает ее.

Или мне нужно открыть и закрыть базу данных до и после каждого доступа.

Закрытие экземпляра SQLiteDatabase не дает ничего потрясающего, кроме закрытия соединений, но это плохой разработчик, если в настоящий момент есть некоторые соединения. Кроме того, после SQLiteDatabase.close() SQLiteOpenHelper.getWritableDatabase() вернет новый экземпляр.

Есть ли какой-либо вред, если просто оставить его открытым все время?

Нет, нет. Также обратите внимание, что закрытие БД в несвязанный момент и поток, например. в Activity.onStop() может закрыть активные соединения и оставить данные в несогласованном состоянии.

Ответ 4

Вы также можете использовать ContentProvider. Он сделает это для вас.

Ответ 5

Создайте свой собственный контекст приложения, затем откройте и закройте базу данных. Этот объект также имеет метод OnTerminate(), который можно использовать для закрытия соединения. Я еще не пробовал, но, похоже, это лучший подход.

@binnyb: Мне не нравится использовать finalize(), чтобы закрыть соединение. Могу работать, но из того, что я понимаю, писать код в Java finalize() - это плохая идея.