Это ответ на мою проблему, надеюсь, это поможет вам.

ретил эту проблему в моей собственной базе данных. Я искал эту проблему в StackOverflow и пробовал много методов, как уже упоминалось, но эта проблема не была решена. Это хорошо работало в одном потоке, проблема обычно возникает в App Widget, когда я пытаюсь обновить элементы списка.

Вот объяснение:

1. это SQLiteOpenHelper, используемый для получения объекта SQLiteDatabase, так как вы видите, что он одиночный:

 public class PalmDB extends SQLiteOpenHelper {

    public static PalmDB getInstance(final Context context){
        if (sInstance == null){
            synchronized (PalmDB.class) {
                if (sInstance == null) {
                    sInstance = new PalmDB(context.getApplicationContext());
                }
            }
        }
        return sInstance;
    }
}

2.Следующее хранилище используется для запроса и сохранения данных в базе данных. Это абстрактно:

public abstract class BaseStore<T extends Model> {
    private PalmDB mPalmDatabase = null;

    @SuppressWarnings("unchecked")
    public BaseStore(Context context) {
        this.mPalmDatabase = PalmDB.getInstance(context);
    }

    protected SQLiteDatabase getWritableDatabase() {
        return mPalmDatabase.getWritableDatabase();
    }

    protected synchronized void closeCursor(Cursor cursor) {
        if (cursor == null || cursor.isClosed()) return;
        try {
            cursor.close();
        } catch (Exception e){
            LogUtils.d("Couldn't close cursor correctly");
        }
    }

    public synchronized List<T> get(String whereSQL, String orderSQL, Status status, boolean exclude) {
        Cursor cursor = null;
        List<T> models = null;
        SQLiteDatabase database = getWritableDatabase();
        try {
            cursor = database.rawQuery(" SELECT * FROM " + tableName
                        + " WHERE " + BaseSchema.USER_ID + " = " + userId
                        + (TextUtils.isEmpty(whereSQL) ? "" : " AND " + whereSQL)
                        + (status == null ? "" : " AND " + BaseSchema.STATUS + (exclude ? " != " : " = ") + status.id)
                        + (TextUtils.isEmpty(orderSQL) ? "" : " ORDER BY " + orderSQL),
                new String[]{});
            models = getList(cursor);
        } finally {
            closeCursor(cursor);
        }
        return models;
    }

    protected synchronized List<T> getList(Cursor cursor){
        LogUtils.d(this); // print the hash code of this object
        LogUtils.d(Thread.currentThread());
        List<T> models = new LinkedList<>();
        if (cursor != null && !cursor.isClosed() && cursor.moveToFirst()){ // exception here
            do {
                models.add(getModel(cursor));
            } while (cursor.moveToNext());
        } else if (cursor != null && cursor.isClosed()) {
            LogUtils.e("cursor is closed : " + cursor);
        }
        return models;
    }

    private T getModel(Cursor cursor) {
        T model = StoreHelper.getBaseModel(cursor, entityClass);
        fillModel(model, cursor);
        return model;
    }

3. Затем я переопределяю этот класс для конкретного объекта, подобного этому. Как вы можете видеть, что это также синглтон:

public class MindSnaggingStore extends BaseStore<MindSnagging> {
    private static MindSnaggingStore sInstance = null;

    public static MindSnaggingStore getInstance(Context context){
        if (sInstance == null){
            synchronized (MindSnaggingStore.class) {
                if (sInstance == null) {
                    sInstance = new MindSnaggingStore(context.getApplicationContext());
                }
            }
        }
        return sInstance;
    }

    private MindSnaggingStore(Context context) {
        super(context);
    }
}

Это работало отлично в действиях и фрагментах, но когда я включаю это в Виджет Приложения. Когда я пытаюсь удалить какие-либо объекты, как правило, дважды, то происходит сбой.

Вот исключение:

02-05 20:01:58.497 19317-19330/? E/AndroidRuntime: FATAL EXCEPTION: Binder:19317_1
                                               Process: me.shouheng.notepal, PID: 19317
                                               java.lang.IllegalStateException: Cannot perform this operation because the connection pool has been closed.
                                                   at android.database.sqlite.SQLiteConnectionPool.throwIfClosedLocked(SQLiteConnectionPool.java:962)
                                                   at android.database.sqlite.SQLiteConnectionPool.waitForConnection(SQLiteConnectionPool.java:599)
                                                   at android.database.sqlite.SQLiteConnectionPool.acquireConnection(SQLiteConnectionPool.java:348)
                                                   at android.database.sqlite.SQLiteSession.acquireConnection(SQLiteSession.java:894)
                                                   at android.database.sqlite.SQLiteSession.executeForCursorWindow(SQLiteSession.java:834)
                                                   at android.database.sqlite.SQLiteQuery.fillWindow(SQLiteQuery.java:62)
                                                   at android.database.sqlite.SQLiteCursor.fillWindow(SQLiteCursor.java:143)
                                                   at android.database.sqlite.SQLiteCursor.getCount(SQLiteCursor.java:132)
                                                   at android.database.AbstractCursor.moveToPosition(AbstractCursor.java:219)
                                                   at android.database.AbstractCursor.moveToFirst(AbstractCursor.java:258)
                                                   at me.shouheng.notepal.provider.BaseStore.getList(BaseStore.java:330)
                                                   at me.shouheng.notepal.provider.BaseStore.get(BaseStore.java:127)
                                                   at me.shouheng.notepal.provider.BaseStore.get(BaseStore.java:101)
                                                   at me.shouheng.notepal.widget.desktop.ListRemoteViewsFactory.getNotes(ListRemoteViewsFactory.java:72)
                                                   at me.shouheng.notepal.widget.desktop.ListRemoteViewsFactory.setupModels(ListRemoteViewsFactory.java:63)
                                                   at me.shouheng.notepal.widget.desktop.ListRemoteViewsFactory.onDataSetChanged(ListRemoteViewsFactory.java:86)
                                                   at android.widget.RemoteViewsService$RemoteViewsFactoryAdapter.onDataSetChanged(RemoteViewsService.java:142)
                                                   at com.android.internal.widget.IRemoteViewsFactory$Stub.onTransact(IRemoteViewsFactory.java:49)
                                                   at android.os.Binder.execTransact(Binder.java:565)

Я добавил sychronized к важным методам, а класс db - singleton, и я удивляюсь, почему проблема все еще возникает.

Больше информации. Ниже мой журнал, я напечатал поток, базу данных и хранилище объектов:

02-05 22:41:53.119 15712-15712/me.shouheng.notepal D/colorful: ThemeDelegate fetched theme in 1 ms
02-05 22:41:53.305 3030-3149/system_process I/ActivityManager: Displayed me.shouheng.notepal/.activity.TrashedActivity: +235ms
02-05 22:41:53.648 15712-15712/me.shouheng.notepal D/NotePal: [ (BaseStore.java:327)#GetList ] me.shouheng.notepal.provider.NotebookStore@76f9b87
02-05 22:41:53.649 15712-15712/me.shouheng.notepal D/NotePal: [ (BaseStore.java:328)#GetList ] Thread[main,5,main]
02-05 22:41:53.656 15712-15712/me.shouheng.notepal D/NotePal: [ (BaseStore.java:327)#GetList ] me.shouheng.notepal.provider.NotesStore@f4252
02-05 22:41:53.656 15712-15712/me.shouheng.notepal D/NotePal: [ (BaseStore.java:328)#GetList ] Thread[main,5,main]

02-05 22:41:58.018 15712-15712/me.shouheng.notepal D/NotePal: [ (BaseStore.java:41)#<init> ] me.shouheng.notepal.provider.PalmDB@a34edfa
02-05 22:41:58.057 15712-15712/me.shouheng.notepal D/NotePal: [ (AppWidgetUtils.java:20)#NotifyAppWidgets ] Notifies AppWidget data changed for widgets [87, 85]
02-05 22:41:58.061 15712-15712/me.shouheng.notepal D/NotePal: [ (BaseStore.java:327)#GetList ] me.shouheng.notepal.provider.NotebookStore@76f9b87
02-05 22:41:58.062 15712-15712/me.shouheng.notepal D/NotePal: [ (BaseStore.java:328)#GetList ] Thread[main,5,main]
02-05 22:41:58.071 15712-15712/me.shouheng.notepal D/NotePal: [ (BaseStore.java:327)#GetList ] me.shouheng.notepal.provider.NotesStore@f4252
02-05 22:41:58.072 15712-15712/me.shouheng.notepal D/NotePal: [ (BaseStore.java:328)#GetList ] Thread[main,5,main]
02-05 22:41:58.155 15712-15712/me.shouheng.notepal D/NotePal: [ (ListRemoteViewsFactory.java:51)#OnCreate ] Created widget 87
02-05 22:41:58.157 15712-15712/me.shouheng.notepal D/NotePal: [ (BaseStore.java:41)#<init> ] me.shouheng.notepal.provider.PalmDB@a34edfa
02-05 22:41:58.158 15712-15712/me.shouheng.notepal D/NotePal: [ (ListRemoteViewsFactory.java:78)#GetMinds ] me.shouheng.notepal.provider.MindSnaggingStore@f341cfd
02-05 22:41:58.158 15712-15712/me.shouheng.notepal D/NotePal: [ (ListRemoteViewsFactory.java:79)#GetMinds ] Thread[main,5,main]
02-05 22:41:58.160 15712-15712/me.shouheng.notepal D/NotePal: [ (BaseStore.java:327)#GetList ] me.shouheng.notepal.provider.MindSnaggingStore@f341cfd
02-05 22:41:58.161 15712-15712/me.shouheng.notepal D/NotePal: [ (BaseStore.java:328)#GetList ] Thread[main,5,main]
02-05 22:41:58.169 15712-15712/me.shouheng.notepal D/NotePal: [ (ListRemoteViewsFactory.java:51)#OnCreate ] Created widget 85
02-05 22:41:58.171 15712-15712/me.shouheng.notepal D/NotePal: [ (BaseStore.java:327)#GetList ] me.shouheng.notepal.provider.NotesStore@f4252
02-05 22:41:58.172 15712-15712/me.shouheng.notepal D/NotePal: [ (BaseStore.java:328)#GetList ] Thread[main,5,main]
02-05 22:41:58.172 15712-16198/me.shouheng.notepal D/NotePal: [ (ListRemoteViewsFactory.java:85)#OnDataSetChanged ] onDataSetChanged widget 87
02-05 22:41:58.173 15712-16198/me.shouheng.notepal D/NotePal: [ (ListRemoteViewsFactory.java:78)#GetMinds ] me.shouheng.notepal.provider.MindSnaggingStore@f341cfd
02-05 22:41:58.173 15712-16198/me.shouheng.notepal D/NotePal: [ (ListRemoteViewsFactory.java:79)#GetMinds ] Thread[Binder:15712_3,5,main]
02-05 22:41:58.174 15712-16198/me.shouheng.notepal D/NotePal: [ (BaseStore.java:327)#GetList ] me.shouheng.notepal.provider.MindSnaggingStore@f341cfd
02-05 22:41:58.175 15712-16198/me.shouheng.notepal D/NotePal: [ (BaseStore.java:328)#GetList ] Thread[Binder:15712_3,5,main]
02-05 22:41:58.177 15712-15725/me.shouheng.notepal D/NotePal: [ (ListRemoteViewsFactory.java:85)#OnDataSetChanged ] onDataSetChanged widget 85
02-05 22:41:58.178 15712-15725/me.shouheng.notepal D/NotePal: [ (BaseStore.java:327)#GetList ] me.shouheng.notepal.provider.NotesStore@f4252
02-05 22:41:58.178 15712-15725/me.shouheng.notepal D/NotePal: [ (BaseStore.java:328)#GetList ] Thread[Binder:15712_1,5,main]
02-05 22:41:58.179 3030-4466/system_process W/InputMethodManagerService: Window already focused, ignoring focus gain of: com.android.internal.view.IInputMethodClient$Stub$Proxy@86f53ab attribute=null, token = android.os.BinderProxy@8dfbb89
02-05 22:41:58.483 15712-16191/me.shouheng.notepal D/OpenGLRenderer: endAllActiveAnimators on 0xc8ecfc00 (MenuPopupWindow$MenuDropDownListView) with handle 0xc8eb0540
02-05 22:41:58.933 3030-3485/system_process D/AudioService: Stream muted, skip playback
02-05 22:41:59.775 3030-3485/system_process D/AudioService: Stream muted, skip playback
02-05 22:41:59.804 15712-15712/me.shouheng.notepal D/NotePal: [ (AppWidgetUtils.java:20)#NotifyAppWidgets ] Notifies AppWidget data changed for widgets [87, 85]
02-05 22:41:59.807 15712-15725/me.shouheng.notepal D/NotePal: [ (ListRemoteViewsFactory.java:85)#OnDataSetChanged ] onDataSetChanged widget 87
02-05 22:41:59.807 15712-16198/me.shouheng.notepal D/NotePal: [ (ListRemoteViewsFactory.java:85)#OnDataSetChanged ] onDataSetChanged widget 85
02-05 22:41:59.808 15712-15725/me.shouheng.notepal D/NotePal: [ (ListRemoteViewsFactory.java:78)#GetMinds ] me.shouheng.notepal.provider.MindSnaggingStore@f341cfd
02-05 22:41:59.808 15712-15712/me.shouheng.notepal D/NotePal: [ (BaseStore.java:327)#GetList ] me.shouheng.notepal.provider.NotebookStore@76f9b87
02-05 22:41:59.808 15712-15725/me.shouheng.notepal D/NotePal: [ (ListRemoteViewsFactory.java:79)#GetMinds ] Thread[Binder:15712_1,5,main]
02-05 22:41:59.808 15712-15712/me.shouheng.notepal D/NotePal: [ (BaseStore.java:328)#GetList ] Thread[main,5,main]
02-05 22:41:59.808 15712-16198/me.shouheng.notepal D/NotePal: [ (BaseStore.java:327)#GetList ] me.shouheng.notepal.provider.NotesStore@f4252
02-05 22:41:59.808 15712-15725/me.shouheng.notepal D/NotePal: [ (BaseStore.java:327)#GetList ] me.shouheng.notepal.provider.MindSnaggingStore@f341cfd
02-05 22:41:59.810 15712-16198/me.shouheng.notepal D/NotePal: [ (BaseStore.java:328)#GetList ] Thread[Binder:15712_3,5,main]
02-05 22:41:59.810 15712-15712/me.shouheng.notepal I/SQLiteConnectionPool: The connection pool for /data/user/0/me.shouheng.notepal/databases/NotePal.db has been closed but there are still 1 connections in use.  They will be closed as they are released back to the pool.
02-05 22:41:59.811 15712-15725/me.shouheng.notepal D/NotePal: [ (BaseStore.java:328)#GetList ] Thread[Binder:15712_1,5,main]
02-05 22:41:59.828 15712-15712/me.shouheng.notepal D/NotePal: [ (BaseStore.java:327)#GetList ] me.shouheng.notepal.provider.NotesStore@f4252
02-05 22:41:59.829 15712-15712/me.shouheng.notepal D/NotePal: [ (BaseStore.java:328)#GetList ] Thread[main,5,main]
02-05 22:41:59.867 15712-15717/me.shouheng.notepal I/art: Do full code cache collection, code=97KB, data=125KB
02-05 22:41:59.868 15712-15717/me.shouheng.notepal I/art: Starting a blocking GC JitCodeCache
02-05 22:41:59.868 15712-15717/me.shouheng.notepal I/art: After code cache collection, code=79KB, data=87KB
02-05 22:41:59.899 3030-14418/system_process W/InputMethodManagerService: Window already focused, ignoring focus gain of: com.android.internal.view.IInputMethodClient$Stub$Proxy@9aae3c6 attribute=null, token = android.os.BinderProxy@8dfbb89
02-05 22:41:59.957 15712-15725/me.shouheng.notepal E/AndroidRuntime: FATAL EXCEPTION: Binder:15712_1
                                                                     Process: me.shouheng.notepal, PID: 15712
                                                                     java.lang.IllegalStateException: Cannot perform this operation because the connection pool has been closed.
                                                                         at android.database.sqlite.SQLiteConnectionPool.throwIfClosedLocked(SQLiteConnectionPool.java:962)
                                                                         at android.database.sqlite.SQLiteConnectionPool.waitForConnection(SQLiteConnectionPool.java:599)
                                                                         at android.database.sqlite.SQLiteConnectionPool.acquireConnection(SQLiteConnectionPool.java:348)
                                                                         at androi,d.database.sqlite.SQLiteSession.acquireConnection(SQLiteSession.java:894)
                                                                         at android.database.sqlite.SQLiteSession.executeForCursorWindow(SQLiteSession.java:834)
                                                                         at android.database.sqlite.SQLiteQuery.fillWindow(SQLiteQuery.java:62)
                                                                         at android.database.sqlite.SQLiteCursor.fillWindow(SQLiteCursor.java:143)
                                                                         at android.database.sqlite.SQLiteCursor.getCount(SQLiteCursor.java:132)
                                                                         at android.database.AbstractCursor.moveToPosition(AbstractCursor.java:219)
                                                                         at android.database.AbstractCursor.moveToFirst(AbstractCursor.java:258)
                                                                         at me.shouheng.notepal.provider.BaseStore.getList(BaseStore.java:330)
                                                                         at me.shouheng.notepal.provider.BaseStore.get(BaseStore.java:127)
                                                                         at me.shouheng.notepal.provider.BaseStore.get(BaseStore.java:101)
                                                                         at me.shouheng.notepal.widget.desktop.ListRemoteViewsFactory.getMinds(ListRemoteViewsFactory.java:80)
                                                                         at me.shouheng.notepal.widget.desktop.ListRemoteViewsFactory.setupModels(ListRemoteViewsFactory.java:65)
                                                                         at me.shouheng.notepal.widget.desktop.ListRemoteViewsFactory.onDataSetChanged(ListRemoteViewsFactory.java:86)
                                                                         at android.widget.RemoteViewsService$RemoteViewsFactoryAdapter.onDataSetChanged(RemoteViewsService.java:142)
                                                                         at com.android.internal.widget.IRemoteViewsFactory$Stub.onTransact(IRemoteViewsFactory.java:49)
                                                                         at android.os.Binder.execTransact(Binder.java:565)

Ответы на вопрос(1)

Ваш ответ на вопрос