2013-08-29 71 views
1

我不知道如何正確處理這個沒有得到數據庫鎖定錯誤。Android sqlite插入/從多個線程多次讀取

我的應用程序基本上以100行(〜60.000項)批量下載許多項目並將它們插入到數據庫中。每批100行都被處理成一個交易。 主要活動允許用戶在記錄下載和插入時在屏幕(片段)之間導航。大多數其他屏幕包含從數據庫讀取的數據。閱讀期間,我收到了很多數據庫鎖定錯誤。所有的讀數都在不同的異步任務

到目前爲止,我只是用「經典方法」

public class DBAdapter { 
public DBAdapter(Context ctx) { 
     this.context = ctx; 
     DBHelper = new DatabaseHelper(context); 
    } 


    private static class DatabaseHelper extends SQLiteOpenHelper { 


     DatabaseHelper(Context context) { 
      super(context, DATABASE_NAME, null, DATABASE_VERSION); 

     } 

     @Override 
     public void onCreate(SQLiteDatabase db) { 
      db.execSQL(DB_CREATE_TABLES); 

     } 

     @Override 
     public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) { 
      Utils.log("Upgrading database from version " + oldVersion + " to " + newVersion + ", which will destroy all old data"); 
      onCreate(db); 
     } 

    public DBAdapter open() throws SQLException { 
     database = DBHelper.getWritableDatabase(); 
     return this; 
    } 

    public void close() { 
     DBHelper.close(); 
    } 

然後在我的活動的onCreate()我叫db = new DBAdapter(context);每一次的主要活動(不片段)完成我在做一個數據庫操作(讀/寫)我叫db.open()和插入/讀取完成後,我打電話db.close()

我的問題是:

  1. 這種情況最好的辦法是什麼?
  2. 考慮到我做了大量的寫入/讀取,onDestroy()上的onCreate和db.close()調用db.open會更好嗎?這會比每次需要訪問數據庫時打開/關閉都好嗎?
  3. 我需要做什麼來避免數據庫在讀取時鎖定?

回答

0

我有一個類似你的情況。除了你所描述的,在我的應用程序中,用戶還可以通過屏幕上的輸入來更新數據庫。 我解決它的方式(我不知道這是最好的方式,但我幾乎看不到任何鎖定問題現在)

  • 建立從SQLiteOpenHelper衍生,以確保只有一個實例一個單獨的類,在任何運行給定的時間。
  • 實現插入/更新/刪除/查詢操作的ContentProvider類。使所有這些功能'同步'
  • 只關閉ContentProvider的關閉功能中的數據庫。我做了非常頻繁的數據庫操作,所以我不想每次都打開/關閉。但我不確定這是否是正確的處理方式。
  • 從任何地方只通過ContentProvider接口訪問數據庫
0

考慮將SQLite數據庫包裝到ContentProvider中,並使用CursorLoader從各種活動&分段中執行查詢。這將數據庫的管理與Activity/Fragment生命週期隔離開來,並可能導致更少的打開/關閉循環。

您仍然可能會在讀取和寫入之間發生爭用,但在同一個模塊中進行所有數據庫交互應該可以讓您更輕鬆地解決這些問題。

一些相關鏈接:http://www.vogella.com/articles/AndroidSQLite/article.html#todo

When to use a Content Provider

0

一個很簡單的辦法,或者一個解決方法是使用開synchronized方法和關閉數據庫對象。我不知道這是否是最佳做法,但至少它簡單易行。將這些方法添加到您的DBAdapter類中,並使用它們代替db.open和db.close。 use_count屬性簡單地保存了打開被調用的次數。使用值0初始化它。另外,爲了使它適用於您的解決方案,請確保在碎片之間傳遞相同的DBAdapter對象。不要每次創建一個新的:

private int use_count = 0; 
public synchronized void doOpen() 
{ 
    use_count++; 
    this.open(); 
} 

public synchronized void doClose() 
{ 
    use_count--; 
    if (use_count == 0) 
    { 
     this.close(); 
    } 
}