Android 併發、多線程操作SQLite數據庫 處理UI主線程阻塞 導致UI界面卡住

今天Android項目上有個bug(蛋疼不我寫的代碼)一個業務多次頻繁調用之後會把主線程ui(主要是時間)卡住了,要一個一個的找錯誤位置,錯誤定位很重要。

一開始是找到了問題的所在(以爲是)調用了主線程的Handler

Handler handler = new Handler(mContext.getMainLooper());
handler.post(........);

坑啊 裏面還有一些網絡請求等耗時操作。。。。。。

但是去掉之後發現問題還是沒有解決!最後百般折騰一個一個模塊去掉之後把問題定位在了操作多線程SQLite數據庫上面

多線程操作SQLite有很多解決方案。我使用了AtomicInteger 原子操作類他是線程安全的來控制多線程情況下只拿到一個SQLiteDatabase實力對象。前提是SQLiteOpenHelper一定要使用單例模式只存在唯一一個。

代碼:

private AtomicInteger mOpenCounter = new AtomicInteger();
private SQLiteDatabase myDataBase = null;

public synchronized SQLiteDatabase getSQLiteDatabase() {
	if (mOpenCounter.incrementAndGet() == 1) {
		myDataBase = SQLHelper.getWritableDatabase();

	}

	return myDataBase;
}

拿到同一個之後SQLiteDatabase之後也要使用同樣的方法來close

	public synchronized void closeDatabase() {
		if (mOpenCounter.decrementAndGet() == 0) {
			myDataBase.close();
		}
	}

這樣子測試之後發現有時候處理一定數量數據之後會出現

W/SQLiteConnectionPool: The connection pool for database '/data/data/com.wbm.app.pda/databases/xxxxx.db' 

has been unable to grant a connection to thread 163308 (Thread-163308) with flags 0x1 for 60.001003 seconds. Connections: 0 active, 1 idle, 0 available.

如果有這種情況的話應該是在使用了SQLiteDatabase的事務beginTransaction 在沒有endTransaction之前在操作數據庫查詢等操作

注意要控制好異常要在catch或者finally中及時的endTransaction和SQLiteDatabase的關閉操作(也要在多線程的情況下進行也就是加了原子操作類來控制的close方法比如上面的closeDatabase)

 

 

 

 

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章