Как правильно открыть/закрыть 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 заботится о закрытии при уничтожении приложения