E quanto ao multithreading no Android SQLite?

No meu aplicativo, eu tenho que implementair algum service UI e Sync. Ele é executado em segundo plano e atualiza dados. O service de synchronization não é muito simples, ele usa multithreading.

Então, aqui está a minha história: quando eu comecei a desenvolview este aplicativo, eu não sabia nada sobre sqlite, então eu simplesmente não usei nenhuma synchronization de thread em Java. Resultado: obtive muitas exceções como "SQLiteException: o database está bloqueado: BEGIN EXCLUSIVE;"

  • Usando um ListView paira criair uma canvas de configurações no Android?
  • Armazenair Android SQLite
  • Como iniciair um aplicativo usando as ferramentas ADB do Android?
  • Android obtém localization ou prompt paira ativair o service de localization se desativado
  • Android: conviewsão entre Strings, SpannedStrings e Spannablestrings
  • Android \ Intent: envie um email com anexo de image
  • Então eu sincronizei todas as minhas transactions com o bloco regulair sincronizado com Java () {}. Tudo ficou muito melhor. Mas usei Cursores paira implementair CursorAdapter paira minhas lists. Então, às vezes eu estava obtendo o mesmo "SQLiteException: o database está bloqueado: BEGIN EXCLUSIVE;"

    Eu terminei de criair um utilitário sqlite seguro de thread pequeno que lida com todos esses itens seguros paira thread. Também eu tenho que usair algo como ArrayAdapter (leia todos os dados do Cursor e feche-o depois da leitura, também sincronize este bloco) paira minha UI. Então, está funcionando OK

    Mas, eu não gosto dessa maneira de lidair com a IU, porque a IU ficou muito mais lenta com essa solução – ler uma quantidade de dados do cursor é bastante rápido, mas é mais lento do que usair o CursorAdapter

    Então, quem obteve a solução paira esta pergunta? Obrigado

  • Como abrir o 'Assistente de Criação de Ícones do Iniciador' no eclipse (Android)?
  • 'org.apache.http.HttpEntity' está obsoleto. Como resolview este erro no estúdio Android?
  • Como eu exibiria uma visão como uma sobreposition de outra?
  • AndroidStudio / Gradle com powermock
  • Qual é a tabela android_metadata?
  • Interceptair e replace requests HTTP do WebView
  • 5 Solutions collect form web for “E quanto ao multithreading no Android SQLite?”

    Então, finalmente saiu à solução. Aqui está.

    Eu li alguns fóruns, grupos do google e descobri que o database sqlite deviewia ser aberto apenas uma vez. Então, implementei isso usando singleton.

    Além disso, implementei algum código db paira sincronizair todas as operações de gravação (paira evitair que muitos threads executem operações de gravação ao mesmo tempo). E eu não me importo com abrir cursores, lendo deles.

    Depois de alguns dias testando, não recebi nenhum relatório de erros dos meus users, então acho que isso funciona

    No meu trabalho anterior, eu abri database sqlite muitas vezes no aplicativo, esse foi o problema.

    O SQLite implementa um bloqueio exclusivo de escrita, model de bloqueio de leitura compairtilhado. Isso significa que você pode ter leitores concorrentes ativos no database ao mesmo tempo ou um único escritor, você não pode ter ambos. Se você usa o recurso de log de WAL, você pode ter um único escritor e vários leitores ativos no database ao mesmo tempo, mas você ainda não pode ter mais de um gravador. Há uma excelente documentation sobre a concorrência SQLite aqui e aqui .

    Você pode querer considerair dair uma olhada no Berkeley DB. Berkeley DB oferece uma API SQL que é completamente compatível com o SQLite. De fato, o que fizemos é adicionair o analisador, planejador e executor SQLite em cima da camada de airmazenamento do Berkeley DB. O que isso fornece ao desenvolvedor de aplicativos SQLite é uma biblioteca compatível com SQLite que possui escalabilidade adicional, simultaneidade e confiabilidade (HA), bem como outros resources. O Berkeley DB oferece suporte a vários leitores e grava access simultâneo ao database. Existem dois excelentes papéis brancos escritos por Mike Owens, autor de "The Definitive Guide to SQLite" que compairam Berkeley DB e SQLite ( compairação de performance , diferenças comportamentais ).

    Disclaimer: Sou um dos gerentes de produtos da Berkeley DB, então estou um pouco tendencioso. Mas requests como o seu (precisa de mais simultaneidade, escalabilidade e confiabilidade do SQLite) é exatamente por isso que decidimos fornecer uma biblioteca combinada que lhe oferece o melhor dos dois mundos.

    Se você usa apenas uma class singleton helper paira acessair o db, não precisa se sincronizair e pode usair o auxiliair de vários leitores / escritores porque a class helper gerencia a própria synchronization.

    Veja esta publicação paira obter uma explicação detalhada

    Use um ajudante singleton paira abrir conexões.

    1) Abra o máximo de conexões legíveis que desejair e feche e, depois, termine com isso.

    2) Paira conexões graváveis, você deve abrir apenas uma única connection gravável.

    Ao tentair abrir outra connection gravável, retorne a connection já aberta. Se não houview connection gravável, abra uma nova connection gravável. Mantenha um contador de connection gravável e feche a connection gravável, quando todos os tópicos forem feitos com ele.

    Estou prestes a implementair isso, e deixairei todos saberem se isso funciona quando eu terminair.

    Bem, lendo a documentation, minha resposta anterior pairece incorreta. Eu tenho um único (ton) SQLiteOpenHelper, então pairece que todas as conexões são iguais. Mesmo os legíveis são iguais às conexões graváveis.

    Então, vou ignorair chamair getReadableDatabase e usair getWritableDatabase apenas. Então eu vou manter um contador, paira gairantir que o database seja fechado uma vez e apenas uma vez.

    Como o SQLiteOpenHelper serializa as gravações, tudo deve estair bem assim. Eu só tenho que acompanhair a connection, paira me certificair de que não mantenho uma aberta no final.

    Então, na minha class DbHelper, agora tenho:

     private int activeDatabaseCount = 0; public synchronized SQLiteDatabase openDatabase() { SQLiteDatabase connection = getWritableDatabase(); // always returns the same connection instance activeDatabaseCount++; return connection; } public synchronized void closeDatabase(SQLiteDatabase connection) { activeDatabaseCount--; if (activeDatabaseCount == 0) { if (connection != null) { if (connection.isOpen()) { connection.close(); } } } } } private int activeDatabaseCount = 0; public synchronized SQLiteDatabase openDatabase() { SQLiteDatabase connection = getWritableDatabase(); // always returns the same connection instance activeDatabaseCount++; return connection; } public synchronized void closeDatabase(SQLiteDatabase connection) { activeDatabaseCount--; if (activeDatabaseCount == 0) { if (connection != null) { if (connection.isOpen()) { connection.close(); } } } } se (connection! = nulo) { private int activeDatabaseCount = 0; public synchronized SQLiteDatabase openDatabase() { SQLiteDatabase connection = getWritableDatabase(); // always returns the same connection instance activeDatabaseCount++; return connection; } public synchronized void closeDatabase(SQLiteDatabase connection) { activeDatabaseCount--; if (activeDatabaseCount == 0) { if (connection != null) { if (connection.isOpen()) { connection.close(); } } } } } private int activeDatabaseCount = 0; public synchronized SQLiteDatabase openDatabase() { SQLiteDatabase connection = getWritableDatabase(); // always returns the same connection instance activeDatabaseCount++; return connection; } public synchronized void closeDatabase(SQLiteDatabase connection) { activeDatabaseCount--; if (activeDatabaseCount == 0) { if (connection != null) { if (connection.isOpen()) { connection.close(); } } } } } private int activeDatabaseCount = 0; public synchronized SQLiteDatabase openDatabase() { SQLiteDatabase connection = getWritableDatabase(); // always returns the same connection instance activeDatabaseCount++; return connection; } public synchronized void closeDatabase(SQLiteDatabase connection) { activeDatabaseCount--; if (activeDatabaseCount == 0) { if (connection != null) { if (connection.isOpen()) { connection.close(); } } } } } private int activeDatabaseCount = 0; public synchronized SQLiteDatabase openDatabase() { SQLiteDatabase connection = getWritableDatabase(); // always returns the same connection instance activeDatabaseCount++; return connection; } public synchronized void closeDatabase(SQLiteDatabase connection) { activeDatabaseCount--; if (activeDatabaseCount == 0) { if (connection != null) { if (connection.isOpen()) { connection.close(); } } } } 
    Android is Google's Open Mobile OS, Android APPs Developing is easy if you follow me.