我有正在由一個CursorAdapter
從LoaderManager
得到了Cursor
的活動填充Fragment
個系列ListView
對象。據我所知,所有數據庫和Cursor
關閉行動完全由LoaderManager
和ContentProvider
處理,所以在任何代碼我都不打電話.close()
任何東西。IllegalStateException異常「試圖重新打開已關閉的對象」在SimpleCursorAdapter從ContentProvider的
但是,有時候,我得到這個異常:
02-19 11:07:12.308 E/AndroidRuntime(18777): java.lang.IllegalStateException: attempt to re-open an already-closed object: android.database.sqlite.SQLiteQuery (mSql = SELECT * FROM privileges WHERE uuid!=?)
02-19 11:07:12.308 E/AndroidRuntime(18777): at android.database.sqlite.SQLiteClosable.acquireReference(SQLiteClosable.java:33)
02-19 11:07:12.308 E/AndroidRuntime(18777): at android.database.sqlite.SQLiteQuery.fillWindow(SQLiteQuery.java:82)
02-19 11:07:12.308 E/AndroidRuntime(18777): at android.database.sqlite.SQLiteCursor.fillWindow(SQLiteCursor.java:164)
02-19 11:07:12.308 E/AndroidRuntime(18777): at android.database.sqlite.SQLiteCursor.onMove(SQLiteCursor.java:147)
02-19 11:07:12.308 E/AndroidRuntime(18777): at android.database.AbstractCursor.moveToPosition(AbstractCursor.java:178)
02-19 11:07:12.308 E/AndroidRuntime(18777): at android.database.CursorWrapper.moveToPosition(CursorWrapper.java:162)
02-19 11:07:12.308 E/AndroidRuntime(18777): at android.widget.CursorAdapter.getView(CursorAdapter.java:241)
我把一些日誌代碼到我的CursorAdapter
告訴我,當getView(...)
,getItem(...)
或getItemId(...)
被調用,它好像這對正在發生的事情第一個getView(...)
對於一個給定的適配器,在很多getView(...)
之後用於另一個適配器。它也發生在用戶在應用程序周圍導航很多之後。
這使我懷疑,如果Cursor
爲適配器被保留在CursorAdapter
,而是由ContentProvider
或Loader
被錯誤地關閉。這可能嗎?我應該根據app/activity/fragment生命週期事件對CursorAdapter
做任何管家嗎?
ContentProvider
查詢方法:
class MyContentProvider extends ContentProvider {
//...
@Override
public Cursor query(Uri uri, String[] projection, String selection,
String[] selectionArgs, String sortOrder) {
SQLiteDatabase db = mOpenHelper.getReadableDatabase();
Cursor query = db.query(getTableName(uri), projection, selection, selectionArgs, null, null, sortOrder);
query.setNotificationUri(getContext().getContentResolver(), uri);
return query;
}
//...
}
典型LoaderCallbacks
:
LoaderCallbacks<Cursor> mCallbacks = new LoaderCallbacks<Cursor>() {
@Override
public void onLoaderReset(Loader<Cursor> loader) {
mArticleAdapter.swapCursor(null);
}
@Override
public void onLoadFinished(Loader<Cursor> loader, Cursor cursor) {
if(cursor.isClosed()) {
Log.d(TAG, "CURSOR RETURNED CLOSED");
Activity activity = getActivity();
if(activity!=null) {
activity.getLoaderManager().restartLoader(mFragmentId, null, mCallbacks);
}
return;
}
mArticleAdapter.swapCursor(cursor);
}
@Override
public Loader<Cursor> onCreateLoader(int id, Bundle args) {
triggerArticleFeed();
CursorLoader cursorLoader = null;
if(id == mFragmentId) {
cursorLoader = new CursorLoader(getActivity(),
MyContentProvider.ARTICLES_URI,
null,
ArticlesContentHelper.ARTICLES_WHERE,
ArticlesContentHelper.ARTICLES_WHEREARGS,
null);
}
return(cursorLoader);
}
};
CursorAdapter
構造:
public ArticlesCursorAdapter(Context context, Cursor c) {
super(context, c, 0);
mImageloader = new ImageLoader(context);
}
我讀過這個問題,但遺憾的是它沒有得到答案我的問題,因爲它只是建議usi ng ContentProvider
,我就是。
IllegalStateException: attempt to re-open an already-closed object. SimpleCursorAdapter problems
剛剛顯露出來
重要新信息我在沒有使用Loader
S和無法正常管理其Cursor
S中的項目在其他地方發現了一些其他的代碼。我剛剛切換了這段代碼以使用與上面相同的模式;然而,如果解決了這個問題,那麼在某個項目的某個部分會出現一個非託管的Cursor
可能會在其他地方殺死一個正確管理的項目。
堅持。
觀察新信息
沒有解決它。
NEW IDEA
@Override
onDestroyView() {
getActivity().getLoaderManager().destroyLoader(mFragmentId);
//any other destroy-time code
super.onDestroyView()
}
即可能是的,我應該將在CursorAdapter
(或者說CursorLoader
與生命週期事件系)做家政服務。
觀察NEW IDEA
都能跟得上的。
上一頁IDEA
原來工作,一旦我在一個小調整加入!不過,這很複雜,我應該重寫整個問題。
我們展示一些代碼...'ContentProvider.query'和'OnLoadCompleteListener.onLoadComplete' – Selvin 2013-02-19 11:46:52
OK詳細信息...在'onLoadComplete'你應該簡單地使用'Adapter.swapCursor(newCursor);'.. 。next ...不要在適配器中存儲Cursor實例,只需在適配器內部使用'getCursor()'...所以在光標交換後,您將獲得光標的新實例... – Selvin 2013-02-19 11:53:50
@Selvin這就是我所做的,我只直接使用傳遞給'bindView(...)'的遊標。當光標移動到「CursorAdapter」代碼的位置(我沒有重寫)時,實際上會發生崩潰。 – 2013-02-19 11:59:11