(原創)android Sqlite多線程訪問異常解決方案


     在開發Android的程序的時候sqlite數據庫是經常用到的;在多線程訪問數據庫的時候會出現這樣的異常:java.lang.IllegalStateException: Cannot perform this operation because the connection pool has been closed.java.lang.IllegalStateException: attempt to re-open an already-closed object: SQLiteDatabase: 或java.lang.IllegalStateException: attempt to re-open an already-closed object: SQLiteDatabase:

這樣的異常信息,Sqlite 自身是不支持多線程同時操作的,下面呢我們給出一個解決方案並列出一些項目中用到的代碼。

     我們會用到AtomicInteger,一個提供原子操作的Integer的類。因為Android 依托強大的jdk在使用的時候,不可避免的會用到synchronized關鍵字。而AtomicInteger則通過一種線程安全的加減操作接口,由此我們可以做一個DatabaseManager 這樣的類,具體代碼見下面的代碼塊:

 

public class DatabaseManager {
    
    private AtomicInteger mOpenCounter = new AtomicInteger();
    private static DatabaseManager instance;  
    private static SQLiteOpenHelper mDatabaseHelper;  
    private SQLiteDatabase mDatabase; 
   
    
    public static synchronized void initializeInstance(SQLiteOpenHelper helper) {  
        if (instance == null) {  
            instance = new DatabaseManager();  
            mDatabaseHelper = helper;  
        }  
    }  
    
    public static synchronized DatabaseManager getInstance(SQLiteOpenHelper helper) {  
        if (instance == null) {  
            initializeInstance(helper);
        }  
        return instance;  
    }  
    
    public synchronized SQLiteDatabase getWritableDatabase() {  
        if(mOpenCounter.incrementAndGet() == 1) {  
            // Opening new database  
            mDatabase = mDatabaseHelper.getWritableDatabase();  
        }  
        return mDatabase;  
    }  
    
    public synchronized SQLiteDatabase getReadableDatabase() {  
        if(mOpenCounter.incrementAndGet() == 1) {  
            // Opening new database  
            mDatabase = mDatabaseHelper.getReadableDatabase();  
        }  
        return mDatabase;  
    }  
    
    public synchronized void closeDatabase() {  
        
        if(mOpenCounter.decrementAndGet() == 0) {  
            // Closing database  
            mDatabase.close();  
        }  
    }

在我們進行關閉數據庫的時候判斷 

mOpenCounter.decrementAndGet() == 0 (更新器管理的給定對象的字段的當前值為0)的時候才正式關閉數據庫,就不會出現上述異常。

用方式呢,在我們操作數據庫邏輯代碼中如下使用
首相要取得
mDatabaseManager = DatabaseManager.getInstance(mContext);
對象
    /***
     * 判斷表中是否有值
     */
    public boolean isExistTabValus() {
        boolean flag = false;
        SQLiteDatabase db = mDatabaseManager.getReadableDatabase();//獲取一個可讀的數據庫對象
        Cursor curcor = null;
        try {
            curcor = db.rawQuery("select * from tab ", null);
            while (curcor.moveToNext()) {
                if (curcor.getCount() > 0) {
                    flag = true;
                }
            }
        } catch (Exception e) {
            Log.e(TAG, "isExistTabValus  error");
        } finally {
            if (curcor != null) {
                curcor.close();
            }
            mDatabaseManager.closeDatabase();//關閉數據庫
        }
        return flag;
    }

上面提供一個使用方法,現在項目中使用這種方法關於數據庫的操作從未沒有出現並發的問題,大家可以嘗試一下。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM