Доступ к базе данных SQLite из нескольких потоков - PullRequest
6 голосов
/ 03 июня 2011

Рассмотрим следующее: у меня есть Service, который записывает в БД в AsyncTask.А моя активность читает данные из БД (для простоты рассмотрим поток пользовательского интерфейса).Я обращаюсь к БД, используя SQLiteOpenHelper.Я создаю один экземпляр в Application onCreate () , а затем получаю его по службе и активности.Есть ли вероятность, что моя БД будет заблокирована?Ранее я использовал ContentProvider для таких операций.Хотя он основан на использовании одного экземпляра SQLiteOpenHelper, я решил упростить свой проект, исключив ContentProvider.

Рассмотрим код:

public class App extends Application {

    private OpenHelper openHelper;

    @Override
    public void onCreate(){
        super.onCreate();
            openHelper=new OpenHelper();
    }

        public OpenHelper getHelper(){
            return openHelper;
        }
}

В Деятельности:

OpenHelper helper=(App)getApplication().getHelper();
SQLiteDatabase db=helper.getReadableDatabase();
// Do reading

А внутри Serice, в отдельном потоке:

OpenHelper helper=(App)getApplication().getHelper();
SQLiteDatabase db=helper.getWritableDatabase();
//Do writing

Будет ли этоsafe?

UPD Возможно, это , но вы не знаете, как его использовать.

Ответы [ 5 ]

7 голосов
/ 21 марта 2012

Поздний, поздний ответ.Ты в полном порядке.На самом деле это правильный способ сделать это.Смотрите мой блог: http://touchlabblog.tumblr.com/post/24474750219/single-sqlite-connection/. Просмотрите мой профиль здесь.Много примеров этого.ContentProvdier - это просто много накладных расходов, и он не нужен, если вы не обмениваетесь данными вне своего приложения.Транзакции хороши для ускорения и (очевидно) улучшения согласованности, но не нужны.

Просто используйте один SqliteOpenHelper в своем приложении, и вы в безопасности.

2 голосов
/ 03 июня 2011

Моя ставка: это не безопасно.

Чтобы быть в более безопасной позиции, вы должны использовать транзакции SQL. Начните с beginTransaction() или beginTransactionNonExclusive() и завершите endTransaction(). Как показано здесь

1 голос
/ 29 декабря 2011

Это мое решение. Я создал класс и закрытый статический объект для синхронизации всего доступа к БД.

public class DBFunctions {
// ...
private static Object lockdb = new Object();


/**
 * Do something using DB
 */
public boolean doInsertRecord(final RecordBean beanRecord) {
    // ...
    boolean success = false;

    synchronized (lockdb) {
              // ...
              // 
              // here ... the access to db is in exclusive way
              // 

              // ...
      final SQLiteStatement statement = db.compileStatement(sqlQuery);

        try {
            // execute ...
            statement.execute(); 
            statement.close();

            // ok
            success = true;
        } catch (Exception e) {
            // error
            success = false;
        }
            }

       return success;
    }

}

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

Любые другие предложения ???

0 голосов
/ 16 марта 2012

Просто видел это, пока искал что-то еще.Похоже, эта проблема будет эффективно решена с помощью ContentProvider.Таким образом, как Деятельность, так и Служба могут использовать провайдера контента, и это позаботится о проблемах конкуренции с БД.

0 голосов
/ 03 июня 2011

Хороший вопрос. Моя первая мысль - это не безопасно. Однако, согласно документам SQLite , SQLite может использоваться в 3 режимах. Режим по умолчанию - «сериализованный» режим:

Сериализированные. В сериализованном режиме SQLite может безопасно использоваться несколькими потоками без ограничений

Итак, я предполагаю, что это скомпилировано в сериализованном режиме на Android.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...