Уважаемое хабрасообщество, вот вам загадка. Решаю уже несколько дней. Никогда до этого не связывался с мобильной разработкой, но черт дернул. Задумал приложение по работе с базой данных. А база большая, но это ничего. Все шло хорошо, пока я не добавил слишком много фрагментов и все не полетело в бездну.
Вводная:
В приложении есть несколько фрагментов с ListView. Они наполняются из базы при помощи связки SimpleCursorAdapter'a и Cursor Loader'а.
Предлагаю ознакомиться с логом ошибки:
10-14 19:29:34.313 24409-24409/ru.endid.sqliteproject E/AndroidRuntime﹕ FATAL EXCEPTION: main
Process: ru.endid.sqliteproject, PID: 24409
java.lang.IllegalStateException: attempt to re-open an already-closed object: SQLiteQuery: SELECT _id, name FROM company ORDER BY name
at android.database.sqlite.SQLiteClosable.acquireReference(SQLiteClosable.java:55)
at android.database.sqlite.SQLiteQuery.fillWindow(SQLiteQuery.java:58)
at android.database.sqlite.SQLiteCursor.fillWindow(SQLiteCursor.java:152)
at android.database.sqlite.SQLiteCursor.onMove(SQLiteCursor.java:124)
at android.database.AbstractCursor.moveToPosition(AbstractCursor.java:214)
at android.database.CursorWrapper.moveToPosition(CursorWrapper.java:162)
at android.widget.CursorAdapter.getItemId(CursorAdapter.java:223)
at android.widget.AbsListView.onSaveInstanceState(AbsListView.java:1764)
at android.view.View.dispatchSaveInstanceState(View.java:12728)
at android.view.ViewGroup.dispatchFreezeSelfOnly(ViewGroup.java:2629)
at android.widget.AdapterView.dispatchSaveInstanceState(AdapterView.java:783)
at android.view.ViewGroup.dispatchSaveInstanceState(ViewGroup.java:2615)
at android.view.View.saveHierarchyState(View.java:12711)
at android.app.FragmentManagerImpl.saveFragmentViewState(FragmentManager.java:1577)
at android.app.FragmentManagerImpl.moveToState(FragmentManager.java:951)
at android.app.FragmentManagerImpl.removeFragment(FragmentManager.java:1167)
at android.app.BackStackRecord.run(BackStackRecord.java:641)
at android.app.FragmentManagerImpl.execPendingActions(FragmentManager.java:1447)
at android.app.FragmentManagerImpl$1.run(FragmentManager.java:443)
at android.os.Handler.handleCallback(Handler.java:733)
at android.os.Handler.dispatchMessage(Handler.java:95)
at android.os.Looper.loop(Looper.java:136)
at android.app.ActivityThread.main(ActivityThread.java:5001)
at java.lang.reflect.Method.invokeNative(Native Method)
at java.lang.reflect.Method.invoke(Method.java:515)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:785)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:601)
at de.robv.android.xposed.XposedBridge.main(XposedBridge.java:132)
at dalvik.system.NativeStart.main(Native Method)
Как видно, нет отсылки к месту возникновения исключения в коде. Более того, попытки отловить его с помощью try - catch в местах, вызывающих подозрения, ничего не принесли. В первую очередь - это методы ContentProvider'а для доступа к базе. Вполне ожидаемо, что проблема с этим. Но нет! Так же были проверены методы Loader'a - чисто! В общем, кому интересно, предлагаю поискать вместе.
P.S. нашел точно такую же ошибку на багтрекере Mozilla
здесь. Отличается только sql запросом. По крайней мере, я не одинок в своей проблеме.
P.P.S. Я не замещаю фрагменты, а использую метод add при добавлении нового. Потом, при возврате, забираю из BackStack предыдущий. Если заменить add на replace, ошибка исчезает. Значит, это напрямую связано с фрагментами и загрузчиком курсора. Но отловить ошибку не получается.