Асинхронные задачи и Sqlite

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

Поскольку у меня есть сервис, я получаю ошибки типа «база данных уже закрыта», «база данных не открыта». Мой объект dbHelper статичен. Я вызываю SQLiteDatabase db = this.getWritableDatabase(); в начале каждого метода, который будет обращаться к базе данных. И db.close() в конце каждого метода.

Должен ли я закрыть db.close() только в onDestroy()? ... Решит ли это проблему или есть другой способ?


person sheetal_158    schedule 18.01.2013    source источник
comment
Покажите свой код dbHelper. Вы открываете его один раз в течение жизни приложения?   -  person Mikita Belahlazau    schedule 18.01.2013
comment
да, я открываю его один раз при создании основной активности.   -  person sheetal_158    schedule 18.01.2013
comment
Могу ли я иметь разные обработчики базы данных для одной и той же базы данных?.. Я думаю, это решит мою проблему.   -  person sheetal_158    schedule 18.01.2013
comment
Да, вы можете попробовать иметь разные обработчики для каждого случая. В противном случае вы должны закрыть свой единственный db в onDestroy в основной деятельности.   -  person Mikita Belahlazau    schedule 18.01.2013
comment
я попытался закрыть БД в OnDestroy(). Но тогда служба, работающая в фоновом режиме, не имеет к ней доступа, когда ей это нужно. Я предполагаю, что лучшим решением было бы иметь отдельный помощник БД для активности и обслуживания соответственно.   -  person sheetal_158    schedule 18.01.2013


Ответы (2)


прежде всего, если вы когда-нибудь захотите закрыть базу данных, вы должны проверить, является ли она isOpen().

Теперь, как правило, ваша реализация SQLiteOpenHelper должна быть одноэлементной и переопределять метод close() следующим образом:

@Override
public synchronized void close() {
    mOpenConnections--;
    if (mOpenConnections == 0) {
        super.close();
    }

}

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

@Override
public synchronized void onOpen(SQLiteDatabase db) {
    super.onOpen(db);
    // increment the number of users of the database connection.
    mOpenConnections++;
}

затем, когда вам нужно закрыть базу данных, используйте метод SQLiteOpenHelper.close().

Это должно решить все ваши проблемы.

person kdehairy    schedule 20.01.2013

Единственное решение, которое, как я обнаружил, надежно работает в нескольких действиях, — это вызов getWritableDatabase в методе onCreate каждого действия.

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

person Philip Sheard    schedule 18.01.2013
comment
я попытался использовать отдельный SQLiteOpenHelper для службы. Но если я закрою свое приложение сразу после запуска службы, я получу ошибку «База данных не открыта». Разве служба не должна работать независимо от активности? - person sheetal_158; 18.01.2013
comment
Вероятно, вам лучше не закрывать базу данных явно. Он все равно закрывается, когда помощник удаляется. - person Philip Sheard; 19.01.2013
comment
помощник будет удален, если основная активность будет уничтожена. Но их служба будет продолжать работать в фоновом режиме. Поэтому я сделал отдельный хелпер для сервиса, он работает так, как я хотел. :) - person sheetal_158; 20.01.2013
comment
не делайте отдельный SQLiteOpenHelper для службы. служба является частью приложения и работает в том же процессе (и даже в том же основном потоке, если вы явно не создали новый поток). и вообще это очень плохая идея иметь несколько экземпляров SQLiteOpenHelper, обрабатывающих одну и ту же базу данных. - person kdehairy; 20.01.2013