Как правильно открыть/закрыть SQLite db в Android
У меня есть приложение, которое функционирует должным образом и не заставляет закрыть или сбой. Но когда я смотрю на LogCat, он иногда дает мне это:
05-20 15:24:55.338: E/SQLiteDatabase(12707): close() was never explicitly called on database '/data/data/com.---.--/databases/debt.db'
05-20 15:24:55.338: E/SQLiteDatabase(12707): android.database.sqlite.DatabaseObjectNotClosedException: Application did not close the cursor or database object that was opened here
немного вниз...
05-20 15:24:55.338: E/System(12707): Uncaught exception thrown by finalizer
05-20 15:24:55.338: E/System(12707): java.lang.IllegalStateException: Don't have database lock!
Я не уверен, когда я открою и закрываю свою базу данных?
У меня есть основное действие, которое является просто заставкой. Затем он переходит в действие, которое вызывает ListView, используя информацию из БД; так что именно в этом действии, когда БД сначала открывается.
Существует также еще одно действие, в котором требуется БД, который отделяет его от ListVeew. Когда я должен открывать и закрывать это? Word кажется, что мне просто нужно открыть один раз, а затем закрыть, когда приложение "приостановлено", "остановлено" или "уничтожено".
Если это так, где я могу поместить метод db.close()... в основной экран Splash Screen, где находится onStop и т.д.? или той же Деятельности, что и та, которая открывает БД? или.. есть ли другое место?
UPDATE:
Это строка в коде, в которой ошибка продолжает указывать на:
public void open() throws SQLException {
database = dbHelper.getWritableDatabase();
}
Ответы
Ответ 1
Если вы используете экземпляр класса DatabaseHelper и после инициализации объекта DBHelper каждый раз, когда вы работаете в базе данных, вы должны вызывать открытый метод, прежде чем выполнять работу, а затем создать новый курсор, запросить базы данных, работайте с информацией, которую вы только что сохранили в курсоре, когда вы закончите закрывать курсор, а затем закройте базу данных. Например, если вы хотите захватить каждый элемент в базе данных, вы бы сделали что-то вроде:
...
DataBaseHelper db = new DataBaseHelper(this);
...
db.open();
Cursor cursor = db.getAllItems();
maxCount = cursor.getCount();
Random gen = new Random();
row = gen.nextInt(maxCount); // Generate random between 0 and max
if (cursor.moveToPosition(row)) {
String myString = cursor.getString(1); //here I want the second column
displayString(myString); //private method
}
cursor.close();
db.close();
getAllItems
является общедоступным методом в моем DatabaseHelper
, он выглядит так, если вам интересно
public Cursor getAllItems() {
return db.query(DATABASE_TABLE,
new String[] {
KEY_ROWID,
KEY_NAME
},
null,
null,
null,
null,
null);
}
Вот как я обращаюсь к своей базе данных, и у меня нет каких-либо ошибок, которые у вас есть, и она отлично работает.
Ответ 2
Вероятно, вы неправильно обрабатываете свою базу данных; вы открываете больше экземпляров базы данных, чем вы закрываете.
Существует несколько шаблонов проектирования, которые вы можете использовать, чтобы исправить это поведение. Вы можете запросить этот ответ для получения дополнительной информации.
Ответ 3
Раньше я делал то, что упоминалось выше @Shikima, но в сложных приложениях, которые имеют множество фоновых сервисов, многопоточность и т.д., он может стать настоящим утомительным, когда вам нужно управлять множеством экземпляров базы данных и, кроме того, открывать и закрывать их.
Чтобы преодолеть это, я использовал следующий метод и, похоже, работает нормально.
1.
Объявить и инициализировать экземпляр YourDBHelperClass в Application базовом классе следующим образом:
public class App extends Application {
public static YourDBHelperClass db;
@Override
public void onCreate() {
super.onCreate();
db = new YourDBHelperClass(getApplicationContext());
db.open();
}
}
2.
В вашей деятельности или в любом другом месте, которое вы хотите использовать БД, инициализируйте объект YourDBHelperClass следующим образом:
YourDBHelperClass db = App.db;
И тогда вы можете использовать базу данных в любом случае, не беспокоясь об открытии и закрытии ее вручную каждый раз. SQLiteOpenHelper заботится о закрытии при уничтожении приложения