2012-10-19 25 views
5

Android'de SQlite veritabanından yazmak ve okumak için SQLiteOpenHelper kullanıyorum. Kullanıcı kullanıcı arabirimine tıkladığında AsyncTask kullanarak SQLite veritabanından okudum, ancak tam bir samo anında diğer AsyncTask'ı kullanarak veritabanını veritabanında yazıyor ve yazıyor.Android SQlite multithread erişim

Her x kez veritabanı kilitli özel durum alırım. Bunu nasıl düzeltebilirim? SQlite aynı anda birden fazla iş parçacığı üzerinden erişilebilir mi?

Bunu şu şekilde kullanıyorum: SQLiteOpenHelper'dan uzanan bir veritabanı sınıfım var. Ben onCreate ve ONUPGRADE yöntemlerini uygulamaya ve her şey veritabanından okuma veya veritabanına yazıyorum ben böyle SQLiteDatabase kullanın:

SQLiteDatabase database = null; 
try { 

    database = new Database(context).getWritableDatabase(); 

    .... 
    writing and reading from database... 
    .... 

} catch (Exception e) { 
    e.printStackTrace(); 
} finally { 
    if (database != null) { 
     database.close(); 
    } 
} 

sonunda ben de yakın SQLiteStatements ve imleçler azından ben bunları kullanmak eğer. @Justin cevap kullanmalı ve uygulamada bir tek sınıf veritabanı sınıfı kullanmalı mıyım?

E/SqliteDatabaseCpp(17377): sqlite3_open_v2("/data/data/com.skulptur/databases/LGM.s3db", &handle, 6, NULL) failed 
E/SQLiteDatabase(17377): Failed to open the database. closing it. 
E/SQLiteDatabase(17377):  android.database.sqlite.SQLiteDatabaseLockedException: database is locked 
E/SQLiteDatabase(17377): at android.database.sqlite.SQLiteDatabase.dbopen(Native Method) 
E/SQLiteDatabase(17377): at android.database.sqlite.SQLiteDatabase.openDatabase(SQLiteDatabase.java:983) 
E/SQLiteDatabase(17377): at android.database.sqlite.SQLiteDatabase.openDatabase(SQLiteDatabase.java:956) 
E/SQLiteDatabase(17377): at android.database.sqlite.SQLiteDatabase.openOrCreateDatabase(SQLiteDatabase.java:1021) 
E/SQLiteDatabase(17377): at android.app.ContextImpl.openOrCreateDatabase(ContextImpl.java:750) 
E/SQLiteDatabase(17377): at android.content.ContextWrapper.openOrCreateDatabase(ContextWrapper.java:221) 
E/SQLiteDatabase(17377): at android.database.sqlite.SQLiteOpenHelper.getWritableDatabase(SQLiteOpenHelper.java:149) 
E/SQLiteDatabase(17377): at android.database.sqlite.SQLiteOpenHelper.getReadableDatabase(SQLiteOpenHelper.java:223) 
+0

Bence sqllite üzerindeki android kütüphaneleri ile yapabileceğiniz her şey senkronize edilir. İstisnai yakalamaya çalışabilir ve kilit durumunu alırsanız tekrar deneyemez misiniz? – quinestor

+1

Gönderinizi düzenleyebilir ve istisna ve sebep bildirimlerinin ilk satırlarını verebilir misiniz? Yaptığınız şeyden daha az, kapalı bir veritabanını veya bir şeyi yeniden kullanmak hakkında daha fazla şüpheliyim. – Gray

cevap

7

.

public class MyApp extends Application { 
    // My instance of SQLiteOpenHelper 
    public static DbHelper openHelper; 

    @Override 
    public void onCreate() { 
     super.onCreate(); 
     if (openHelper == null) { 
      openHelper = new DbHelper(this); 
     } 
    } 

    public synchronized static SQLiteDatabase getDB() { 
     return openHelper.getWritableDatabase(); 
    } 
} 

Bunu yaptıktan sonra, bir db sorgusu yapmak istediğimiz zaman, MyApp.getDB gibi db kolu() almak ve bir kilitleme sorunu zorunda kalmayacaksınız. DB'yi ASLA kapatmayacağınızdan emin olun. Bu desen, uygulamanızda her zaman tek bir bağlantıyı korur.

db.beginTransaction(); 
try { 
    for (DBRow row : insertList) { 
     // your insert code 
     insertRow(row); 
     db.yieldIfContendedSafely(); 
    } 
    db.setTransactionSuccessful(); 
} finally { 
    db.endTransaction(); 
} 

Bu, diğer sorgular kendilerini karışmak sağlayacaktır: SQLite uzun tek bir işlemde 1000 uçlar gibi, DB süreçlerini çalışan var bunu böyle kod isteyeceksiniz eğer öyleyse Android'de senkron olması gerekiyordu Böylece, uygulamanızın arka plan güncellemeleri sırasında durduğunu görmezsiniz.

+2

'SQLiteOpenHelper'ınızı' Application' sınıfını geçersiz kılmaktan daha iyi bir singleton yapabilirsiniz. – kdehairy

+0

yep, Bunu yazdıktan sonra şunu farkettim: - \ .. yanıtımı değiştirmek gibi hissetmedim – JustinMorris

+6

Korkarım ki asla bir kilitleme sorununa sahip olmadığın varsayımı hakkında yanılıyorsun: Senkronize edeceğin tek şey senin erişimin. 'getWritableDatabase' yöntemine, yani: sadece * bu * hiçbir zaman aynı anda çağrılmayacaktır, SQLiteDatabase' nesnesinde ne olduğu ile ilgili olarak ne olur, * senkronize edilmez *. – theV0ID

1

denemek için birkaç şey vardır:

Bu

alıyorum hatadır. İlk olarak, her görevinize aynı örneği SQLiteOpenHelper aktarmayı deneyin. İkincisi, SQLiteDatabase'inizin Yardımcınızdaki beginTransaction ve endTransaction'ı kullanmaktadır. Üçüncüsü, görevlerinizde kullanılan her yardımcı yönteminize synchronized ekliyor.

+0

yolun gayet iyi, ama ben ContentProvider'ı tercih ediyorum, app ve db arasında bir ayrım yapıyor. ORMLite ya da başka bir ORM benzeri lib'i de düşünebilirsiniz, bunların birçoğu vardır, iyi bir örnek CROM'dur, bir süre önce yaptığım şey https: // github.com/rysiekblah/crom –

0

Veritabanı bağlantılarını yanlış kullandığınızı düşünüyorum. Kapalı olmayan imleçler veya başka bir şey tarafından kaynaklanabilir. Sqlite veritabanı uygulaması iş parçacığı güvenlidir ve farklı iş parçacıklarından aynı anda erişilebilir. Lütfen size yardımcı olabilmemiz için sorununuz hakkında daha fazla bilgi (istisna yığını izi, istisnaya neden olan kod örneği) verin.