Расширение ответа elhadi Я столкнулся с подобными проблемами при открытии и закрытии соединений с базой данных по нескольким асинхронным задачам. Из моего исследования в то время стало ясно, что нет необходимости постоянно открывать и закрывать соединения db. Подход, который я завершил, заключался в подклассификации Application
и выполнении одиночного db, открытого во время onCreate
, и одного db, закрывающего onTerminate
. Затем я установил статический getter для извлечения уже открытого объекта SQLiteDatabase
. Not DI (Dependency Injection) дружелюбный, но Android пока не может этого сделать.
Нечто подобное;
public class MainApplication extends Application {
private static SQLiteDatabase database;
/**
* Called when the application is starting, before any other
* application objects have been created. Implementations
* should be as quick as possible...
*/
@Override
public void onCreate() {
super.onCreate();
try {
database = SQLiteDatabase.openDatabase("/data/data/<yourdbpath>", null, SQLiteDatabase.OPEN_READWRITE);
} catch (SQLiteException e) {
// Our app fires an event spawning the db creation task...
}
}
/**
* Called when the application is stopping. There are no more
* application objects running and the process will exit.
* <p>
* Note: never depend on this method being called; in many
* cases an unneeded application process will simply be killed
* by the kernel without executing any application code...
* <p>
*/
@Override
public void onTerminate() {
super.onTerminate();
if (database != null && database.isOpen()) {
database.close();
}
}
/**
* @return an open database.
*/
public static SQLiteDatabase getOpenDatabase() {
return database;
}
}
Чтение JavaDoc назад я, конечно, plagerised это где-то, но это статический одиночный дб открыть/закрыть решить этот вопрос вы имеете. На SO есть еще один ответ, где описывается это решение.
Подробнее:
В ответ на комментарий Fr4nz в о с ниже NPE, я предоставил более подробную информацию о нашей конкретной реализации.
Короткая версия
Ниже «полная картина» трудно понять без хорошего понимания BroadcastReceivers. В вашем случае (и в качестве первого) добавьте в код создания базы данных и введите intialise и откройте базу данных после создания базы данных. Так пишите;
try {
database = SQLiteDatabase.openDatabase("/data/data/<yourdbpath>", null, SQLiteDatabase.OPEN_READWRITE);
} catch (SQLiteException e) {
// Create your database here!
database = SQLiteDatabase.openDatabase("/data/data/<your db path>", null, SQLiteDatabase.OPEN_READWRITE);
}
}
Длинная версия
Да, есть немного больше, чем просто приведенный выше код. Обратите внимание на мой комментарий об исключении catch в первом экземпляре (т. Е. При первом запуске приложения). Здесь говорится: «Наше приложение запускает событие, создающее задачу создания db». Что на самом деле происходит в нашем приложении, так это то, что прослушиватель (платформа Android BroadcastReceiver
) зарегистрирован и одной из первых вещей, которые делает основной вид активности приложения, является проверка того, что статическая переменная в MainApplication
не равна нулю. Если он равен нулю, тогда возникает асинхронная задача, которая создает db, который, когда он заканчивается (т.запускает метод onPostExecute()
) в конечном итоге запускает событие, которое, как мы знаем, будет воспринято слушателем, зарегистрированным в try-catch. Приемник живет под классом MainApplication как внутренний класс и выглядит следующим образом;
/**
* Listener waiting for the application to finish
* creating the database.
* <p>
* Once this has been completed the database is ready for I/O.
* </p>
*
* @author David C Branton
*/
public class OpenDatabaseReceiver extends BroadcastReceiver {
public static final String BROADCAST_DATABASE_READY = "oceanlife.core.MainApplication$OpenDatabaseReceiver.BROADCAST_DATABASE_READY";
/**
* @see android.content.BroadcastReceiver#onReceive(android.content.Context, android.content.Intent)
*/
@Override
public void onReceive(final Context context, final Intent intent) {
Log.i(CreatedDatabaseReceiver.class.getSimpleName(), String.format("Received filter event, '%s'", intent.getAction()));
database = SQLiteDatabase.openDatabase("/data/data/<your db path>", null, SQLiteDatabase.OPEN_READWRITE);
unregisterReceiver(openDatabaseReceiver);
// Broadcast event indicating that the creation process has completed.
final Intent databaseReady = new Intent();
databaseReady.setAction(BROADCAST_DATABASE_READY);
context.sendBroadcast(databaseReady);
}
}
Таким образом, краткое изложение процесса запуска для первой установки аналогично;
- Класс: MainApplication, role-check есть база данных?
- Да? переменная базы данных инициализируется
- Нет? Получатель зарегистрирован (
OpenDatabaseReceiver
)
- Класс: MainActivity: Роль-приземление для приложения и изначально проверяет, что переменная базы данных не равна нулю.
database
есть null? Не добавляет в фрагменты, которые выполняют ввод-вывод, и добавляет в диалоговом окне «создание базы данных приложений» или подобное.
database
не имеет значения? Выполняется с основным потоком выполнения приложения, добавляет в списки, поддерживаемые db и т. Д.
- Класс: DatabaseCreationDialogFragment: role-spawns async task для создания базы данных.
- Регистрирует новый приемник, прослушивающий, когда база данных была создана.
- При сборе сообщения «Я создал базу данных» запускается другое событие (из получателя), сообщающее приложению открыть базу данных.
- Класс: MainApplication: role 2- прослушать сообщение, созданное «базами данных».
- Получатель, описанный выше (
OpenDatabaseReceiver
), открывает базу данных и передает (другим событием!), Что база данных готова к использованию.
- Класс: MainActivity: role 2- Подбирает «базу данных готов», устраняет диалоги «мы создаем базу данных» и включаем отображение данных/функций в приложении.
Мир восстановлен.
Не забудьте обновить свой '' '' Manifest.xml'''' путь к новому имени приложения, если вы попытаетесь это сделать. – OceanLife
Спасибо за ответ – Fr4nz
Решила ли ваша проблема Fr4nz? – OceanLife