Я бы держал его открытым все время и закрывал каким-нибудь методом жизненного цикла, например onStop
или onDestroy
. Таким образом, вы можете легко проверить , если база данных уже используется по телефону isDbLockedByCurrentThread
или isDbLockedByOtherThreads
на одном SQLiteDatabase
объекте каждый раз , прежде чем использовать его. это предотвратит множественные манипуляции с базой данных и спасет ваше приложение от потенциального сбоя
поэтому в вашем синглтоне у вас может быть такой метод для получения вашего единственного 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;
}
поэтому всякий раз, когда вы хотите использовать свой открытый вспомогательный объект, вызывайте этот метод получения (убедитесь, что он многопоточен)
другой метод в вашем синглтоне может быть (вызывается КАЖДЫЙ РАЗ, прежде чем вы попытаетесь вызвать метод получения выше):
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();
}
Если пользователи вашего приложения могут очень быстро создавать множество взаимодействий с базой данных, вам следует использовать что-то вроде того, что я продемонстрировал выше. но если взаимодействие с базой данных минимально, я бы не стал беспокоиться об этом и просто каждый раз создавал и закрывал базу данных.
На данный момент нет необходимости проверять, заблокирована ли база данных другим потоком. Хотя вы используете одноэлементный SQLiteOpenHelper в каждом потоке, вы в безопасности. Из
isDbLockedByCurrentThread
документации:isDbLockedByOtherThreads
устарело с API уровня 16.источник
По вопросам:
Мы должны разделить «открытие БД», «открытие соединения». SQLiteOpenHelper.getWritableDatabase () предоставляет открытую БД. Но нам не нужно контролировать соединения, поскольку это делается внутри компании.
Да, это так. Соединения не зависают, если транзакции правильно закрыты. Обратите внимание, что ваша БД также будет автоматически закрыта, если GC завершит ее.
Закрытие экземпляра SQLiteDatabase не дает ничего особенного, кроме закрытия подключений, но это плохо для разработчика, если в данный момент есть какие-то подключения. Кроме того, после SQLiteDatabase.close () SQLiteOpenHelper.getWritableDatabase () вернет новый экземпляр.
Нет, нет. Также обратите внимание, что закрытие БД в несвязанный момент и поток, например, в Activity.onStop (), может закрыть активные соединения и оставить данные в несогласованном состоянии.
источник
В Android 8.1 есть
SQLiteOpenHelper.setIdleConnectionTimeout(long)
метод, который:https://developer.android.com/reference/android/database/sqlite/SQLiteOpenHelper.html#setIdleConnectionTimeout(long)
источник
С точки зрения производительности оптимальный способ - сохранить единственный экземпляр SQLiteOpenHelper на уровне приложения. Открытие базы данных может быть дорогостоящим и является блокирующей операцией, поэтому ее не следует выполнять в основном потоке и / или в методах жизненного цикла активности.
Метод setIdleConnectionTimeout () (представленный в Android 8.1) можно использовать для освобождения оперативной памяти, когда база данных не используется. Если установлен тайм-аут простоя, соединение (я) с базой данных будет закрыто после периода бездействия, т. Е. Когда к базе данных не было доступа. Соединения будут повторно открываться прозрачно для приложения при выполнении нового запроса.
Кроме того, приложение может вызывать releaseMemory (), когда оно переходит в фоновый режим или обнаруживает нехватку памяти, например, в onTrimMemory ().
источник
Вы также можете использовать ContentProvider. Он сделает это за вас.
источник
Создайте свой собственный контекст приложения, затем откройте и закройте базу данных оттуда. Этот объект также имеет метод OnTerminate (), который можно использовать для закрытия соединения. Я еще не пробовал, но кажется, что это лучший подход.
@binnyb: Мне не нравится использовать finalize () для закрытия соединения. Может работать, но из того, что я понимаю, писать код в методе Java finalize () - плохая идея.
источник
onTerminate
не будет вызываться в производственной среде - developer.android.com/reference/android/app/…