Android ava.lang.IllegalStateException: Cannot perform this operation because the connection pool ha

Android开发中遇到如下异常:

07-06 16:54:03.480: E/MtaSDK(24653): java.lang.IllegalStateException: Cannot perform this operation because the connection pool has been closed.
07-06 16:54:03.480: E/MtaSDK(24653): 	at android.database.sqlite.SQLiteConnectionPool.throwIfClosedLocked(SQLiteConnectionPool.java:962)
07-06 16:54:03.480: E/MtaSDK(24653): 	at android.database.sqlite.SQLiteConnectionPool.waitForConnection(SQLiteConnectionPool.java:677)
07-06 16:54:03.480: E/MtaSDK(24653): 	at android.database.sqlite.SQLiteConnectionPool.acquireConnection(SQLiteConnectionPool.java:348)
07-06 16:54:03.480: E/MtaSDK(24653): 	at android.database.sqlite.SQLiteSession.acquireConnection(SQLiteSession.java:894)
07-06 16:54:03.480: E/MtaSDK(24653): 	at android.database.sqlite.SQLiteSession.executeForCursorWindow(SQLiteSession.java:834)
07-06 16:54:03.480: E/MtaSDK(24653): 	at android.database.sqlite.SQLiteQuery.fillWindow(SQLiteQuery.java:62)
07-06 16:54:03.480: E/MtaSDK(24653): 	at android.database.sqlite.SQLiteCursor.fillWindow(SQLiteCursor.java:147)
07-06 16:54:03.480: E/MtaSDK(24653): 	at android.database.sqlite.SQLiteCursor.getCount(SQLiteCursor.java:136)
07-06 16:54:03.480: E/MtaSDK(24653): 	at android.database.AbstractCursorInjector.before_moveToPosition(AbstractCursorInjector.java:24)
07-06 16:54:03.480: E/MtaSDK(24653): 	at android.database.AbstractCursor.moveToPosition(AbstractCursor.java:197)
07-06 16:54:03.480: E/MtaSDK(24653): 	at android.database.AbstractCursor.moveToFirst(AbstractCursor.java:240)
07-06 16:54:03.480: E/MtaSDK(24653): 	at com.xxx.client.db.KeyValueTable.getValueByKey(KeyValueTable.java:46)
07-06 16:54:03.480: E/MtaSDK(24653): 	at com.xxx.client.state.Login.getOpenId(Login.java:146)
07-06 16:54:03.480: E/MtaSDK(24653): 	at com.xxx.client.state.StateManager.isUserLogined(StateManager.java:32)
07-06 16:54:03.480: E/MtaSDK(24653): 	at com.xxx.client.maintab.tabc.TabCFragment.onResume(TabCFragment.java:366)
07-06 16:54:03.480: E/MtaSDK(24653): 	at android.support.v4.app.Fragment.performResume(Fragment.java:1543)
07-06 16:54:03.480: E/MtaSDK(24653): 	at android.support.v4.app.FragmentManagerImpl.moveToState(FragmentManager.java:974)
07-06 16:54:03.480: E/MtaSDK(24653): 	at android.support.v4.app.FragmentManagerImpl.moveToState(FragmentManager.java:1115)
07-06 16:54:03.480: E/MtaSDK(24653): 	at android.support.v4.app.FragmentManagerImpl.moveToState(FragmentManager.java:1097)
07-06 16:54:03.480: E/MtaSDK(24653): 	at android.support.v4.app.FragmentManagerImpl.dispatchResume(FragmentManager.java:1905)
07-06 16:54:03.480: E/MtaSDK(24653): 	at android.support.v4.app.FragmentActivity.onResumeFragments(FragmentActivity.java:466)
07-06 16:54:03.480: E/MtaSDK(24653): 	at android.support.v4.app.FragmentActivity.onPostResume(FragmentActivity.java:455)
07-06 16:54:03.480: E/MtaSDK(24653): 	at android.app.Activity.performResume(Activity.java:5343)
07-06 16:54:03.480: E/MtaSDK(24653): 	at android.app.ActivityThread.performNewIntents(ActivityThread.java:2320)
07-06 16:54:03.480: E/MtaSDK(24653): 	at android.app.ActivityThread.handleNewIntent(ActivityThread.java:2327)
07-06 16:54:03.480: E/MtaSDK(24653): 	at android.app.ActivityThread.access$1600(ActivityThread.java:138)
07-06 16:54:03.480: E/MtaSDK(24653): 	at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1270)
07-06 16:54:03.480: E/MtaSDK(24653): 	at android.os.Handler.dispatchMessage(Handler.java:102)
07-06 16:54:03.480: E/MtaSDK(24653): 	at android.os.Looper.loop(Looper.java:136)
07-06 16:54:03.480: E/MtaSDK(24653): 	at android.app.ActivityThread.main(ActivityThread.java:5014)
07-06 16:54:03.480: E/MtaSDK(24653): 	at java.lang.reflect.Method.invokeNative(Native Method)
07-06 16:54:03.480: E/MtaSDK(24653): 	at java.lang.reflect.Method.invoke(Method.java:515)
07-06 16:54:03.480: E/MtaSDK(24653): 	at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:805)
07-06 16:54:03.480: E/MtaSDK(24653): 	at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:621)
07-06 16:54:03.480: E/MtaSDK(24653): 	at dalvik.system.NativeStart.main(Native Method)

导致这个问题的原因网上有多种,比如嵌套获取了数据库实例,而在里层实例使用完后,关闭了数据库,导致外层调用时出错。

我遇到的情况是:代码中将SQLiteOpenHelper写成了单例模式,每次对数据库的增删改查前打开数据库,操作后关闭数据库;对SQLiteDatabase的增删改查访问都放在了AsyncTask异步任务中执行,而代码中出现了紧接着两次访问SqliteDatabase的情况(一次删除后面紧接着有一次查询操作)。

问题分析

* SQLiteDatabase不支持多线程在不同的数据库连接上并发访问。

* 创建一个 SQLiteOpenHelper 对象时,实际上也是在新建一个数据库连接。

基于以上2点,我遇到情况就是,SQLiteOpenHelper写成了单例,所以紧连着的2次数据库操作使用的是一个数据库连接,两次AsyncTask任务使用的很可能是不同地线程,代码中删除操作完成后就将数据库连接关闭了,从而查询操作时会报上面的错。

后来将查询操作改成了在内存中查询,不让代码这个时候访问数据库,问题解决。

Android下多线程安全访问SQLiteDatabase可参考下面一篇译文和github上的示例demo:

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() {
        if (instance == null) {
            throw new IllegalStateException(DatabaseManager.class.getSimpleName() +
                    " is not initialized, call initializeInstance(..) method first.");
        }

        return instance;
    }

    public synchronized SQLiteDatabase openDatabase() {
        if(mOpenCounter.incrementAndGet() == 1) {
            // Opening new database
            mDatabase = mDatabaseHelper.getWritableDatabase();
        }
        return mDatabase;
    }

    public synchronized void closeDatabase() {
        if(mOpenCounter.decrementAndGet() == 0) {
            // Closing database
            mDatabase.close();

        }
    }
}

http://blog.csdn.net/Sky_Monkey/article/details/23820021

https://github.com/dmytrodanylyk/dmytrodanylyk/blob/gh-pages/articles/Concurrent%20Database%20Access.md





你可能感兴趣的:(Android,Android基础)