Синхронизация SQLiteOpenHelper

Поэтому я придумал какую-то идею, и мне интересно, возможно ли это.

Допустим, у меня есть несколько таблиц (модели баз данных), каждый из которых представлен некоторым классом. Я не хочу использовать одноэлементный шаблон с открытым помощником, поэтому я создал простой класс для предоставления одного экземпляра базы данных. Мой Идея состоит в том, что пока все таблицы содержат ссылку на SQLiteDatabase (возвращенную вспомогательным помощником), все они будут работать с одним и тем же экземпляром DB и, вероятно, не понадобятся для синхронизации работы с базой данных, так как этот помощник делает это. Последняя таблица завершает работу, GC будет собирать открытый помощник (так как последняя ссылка будет слабой ссылкой) -> finalize () вызывается, и я закрываю db во время этого метода, чтобы предотвратить любое предупреждение из ОС. Мой вопрос: может ли это работать? Будет ли он автоматически закрывать базу данных и будет ли она утечка или исключение?

Вот мой класс:

public class DatabaseHelper { private static WeakReference<SomeCustomOpenHelper> sDBOpenHelper; private void notifyDBCreate(SQLiteDatabase db) { for (DBTable table : mTables) { table.onDBCreate(db); } } private void notifyDBUpgrade(SQLiteDatabase db) { for (DBTable table : mTables) { table.onDBUpgrade(db); } } public SQLiteDatabase getDatabase(boolean readOnly) { SomeCustomOpenHelper dbHelper = sDBOpenHelper.get(); if (dbHelper == null) { dbHelper = new SomeCustomOpenHelper(context, name, factory, version, new DatabaseEventsCallback()); sDBOpenHelper = new WeakReference<SomeCustomOpenHelper>(dbHelper); } if (readOnly) { return dbHelper.getReadableDatabase(); } else { return dbHelper.getWritableDatabase(); } } private class DatabaseEventsCallback implements IDatabaseEventsCallback { @Override public void onCreate(SQLiteDatabase db) { notifyDBCreate(db); } @Override public void onUpgrade(SQLiteDatabase db) { notifyDBUpgrade(db); } } interface IDatabaseEventsCallback { void onCreate(SQLiteDatabase db); void onUpgrade(SQLiteDatabase db); } private static class SomeCustomOpenHelper extends SQLiteOpenHelper { private IDatabaseEventsCallback mCB; public SomeCustomOpenHelper(Context context, String name, CursorFactory factory, int version, IDatabaseEventsCallback cb) { super(context, name, factory, version); mCB = cb; } @Override public void onCreate(SQLiteDatabase db) { mCB.onCreate(db); } @Override public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) { mCB.onUpgrade(db); } @Override protected void finalize() throws Throwable { this.close(); super.finalize(); } } } 

Solutions Collecting From Web of "Синхронизация SQLiteOpenHelper"

На самом деле я не знал ответа, но заинтересовался и посмотрел.

Ответ здесь правильно написан; http://blog.foxxtrot.net/2009/01/a-sqliteopenhelper-is-not-a-sqlitetablehelper.html

Но в основном ядро ​​информации;

Я создал три класса SQLiteOpenHelper, по одному для каждой таблицы, хотя все они ссылались только на один файл базы данных.

Здесь все развалилось. Android поддерживает Версии для баз данных на основе связанного с ним пакета, имени базы данных и номера версии, которую вы предоставляете. В пакете и названии указывается, каким будет путь на устройстве, пока версия хранится (где-то) на устройстве, чтобы он знал, когда нужно вызвать обработчик событий OnUpgrade OpenHelper. Оказывается, если в SQLiteOpenHelper Constructor он определяет, что база данных уже существует, она вообще не будет вызывать методы onCreate или onUpgrade, даже если этот класс, вызывающий вызов, никогда ранее не вызывался.

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

Я не уверен, что создание слабой ссылки гарантирует, что экземпляр базы данных будет собран. Однако возможным обходным решением может быть следующее: назначение нулевого значения для экземпляра статической базы данных после завершения всей транзакции базы данных и закрытия базы данных. Это может гарантировать, что экземпляр базы данных больше не выделяет никакой памяти.

Дайте мне знать, если это работает, или если есть более эффективная работа.

Вы можете это сделать. Как вы говорите, блокировка должна происходить на SQLite, и я никогда не слышал об этом проблемах, поэтому с вами все в порядке. Единственное ограничение, которое у вас есть, это то, что все таблицы должны будут поступать в одну базу данных, так как Android теперь позволяет вам иметь только один файл.

Закрытие базы данных – это совсем другое дело, поэтому на самом деле интересно использовать шаблон singleton (вы избегаете закрытия + открытия все время). Тем не менее с вашим подходом вам просто нужно обязательно закрыть db, когда вы закончите с ним. Насколько мне известно, это не делается автоматически.

Кроме того, Ларс Фогель написал чрезвычайно полезные и подробные статьи о доступе к БД в Android. Возможно, вы захотите посмотреть там. http://www.vogella.com/articles/AndroidSQLite/article.html

Вы можете использовать один открытый помощник для всей таблицы. Я также использую один экземпляр в своем приложении так же.

 public static synchronized DatabaseHelper getInstance(Context ctx) { if (dbhelper == null) { dbhelper = new DatabaseHelper(ctx); } return dbhelper ; } 

Мой вопрос: может ли это работать? Будет ли он автоматически закрывать базу данных и будет ли она утечка или исключение?

Нет, он не будет автоматически закрывать базу данных, когда ваше приложение будет требовать для объекта DATABASE, и ОС обнаружила, что какая-то из ваших мгновенных данных в базе данных жива, тогда инфраструктура Android пытается связать эту ссылку с объектом (что, вероятно, является слабым эталоном)

И я должен сказать, что я не рекомендую открывать и закрывать базу данных по требованию или временно. Всегда приятно открывать БД досрочно и держать его открытым на всю вашу деятельность и закрывать его, когда деятельность завершается или приостанавливается.