我正在尝试将CursorLoader与CursorTreeAdapter一起使用,但是遇到了我无法解决的问题. (如果您有一个可行的示例,请随时跳过其余内容,并附在下面.我将非常感谢)
我第一次打开群组时,一切正常.如果然后关闭并重新打开该组,则会收到溢出错误.这是错误:
V/SpellBook(29520): Activity being created
D/SpellBook(29520): onCreateLoader for id 123456
V/SpellBook(29520): Resuming
V/SpellBook(29520): Processing query for uri content://com.zalzala.spellbook.SpellProvider/levels/bard
D/SpellBook(29520): onl oadFinished() for id 123456
D/SpellBook(29520): onCreateLoader for id 3
V/SpellBook(29520): Processing query for uri content://com.zalzala.spellbook.SpellProvider/class/bard/3
D/SpellBook(29520): onl oadFinished() for id 3
这里一切都很好.到目前为止,我已经打开了活动并打开了组3.这是如果我关闭组3并再次打开它会发生的情况:
D/SpellBook(29520): onl oadFinished() for id 3
D/SpellBook(29520): onl oadFinished() for id 3
D/SpellBook(29520): onl oadFinished() for id 3
D/SpellBook(29520): onl oadFinished() for id 3
D/SpellBook(29520): onl oadFinished() for id 3
(... and a lot more of these)
E/AndroidRuntime(29520): FATAL EXCEPTION: main
E/AndroidRuntime(29520): java.lang.*Error
E/AndroidRuntime(29520): at java.util.HashMap.get(HashMap.java:302)
E/AndroidRuntime(29520): at android.database.sqlite.SQLiteCursor.getColumnIndex(SQLiteCursor.java:355)
E/AndroidRuntime(29520): at android.database.CursorWrapper.getColumnIndex(CursorWrapper.java:67)
E/AndroidRuntime(29520): at com.zalzala.spellbook.SpellListView$ExpandableListCursorLoaderFragment$MyExpandableListAdapter.getChildrenCursor(SpellListView.java:216)
E/AndroidRuntime(29520): at android.widget.CursorTreeAdapter.getChildrenCursorHelper(CursorTreeAdapter.java:106)
E/AndroidRuntime(29520): at android.widget.CursorTreeAdapter.setChildrenCursor(CursorTreeAdapter.java:159)
E/AndroidRuntime(29520): at com.zalzala.spellbook.SpellListView$ExpandableListCursorLoaderFragment.onLoadFinished(SpellListView.java:183)
E/AndroidRuntime(29520): at com.zalzala.spellbook.SpellListView$ExpandableListCursorLoaderFragment.onLoadFinished(SpellListView.java:1)
E/AndroidRuntime(29520): at android.support.v4.app.LoaderManagerImpl$LoaderInfo.callOnLoadFinished(LoaderManager.java:413)
E/AndroidRuntime(29520): at android.support.v4.app.LoaderManagerImpl.initLoader(LoaderManager.java:547)
E/AndroidRuntime(29520): at com.zalzala.spellbook.SpellListView$ExpandableListCursorLoaderFragment$MyExpandableListAdapter.getChildrenCursor(SpellListView.java:217)
E/AndroidRuntime(29520): at android.widget.CursorTreeAdapter.getChildrenCursorHelper(CursorTreeAdapter.java:106)
E/AndroidRuntime(29520): at android.widget.CursorTreeAdapter.setChildrenCursor(CursorTreeAdapter.java:159)
E/AndroidRuntime(29520): at com.zalzala.spellbook.SpellListView$ExpandableListCursorLoaderFragment.onLoadFinished(SpellListView.java:183)
E/AndroidRuntime(29520): at com.zalzala.spellbook.SpellListView$ExpandableListCursorLoaderFragment.onLoadFinished(SpellListView.java:1)
E/AndroidRuntime(29520): at android.support.v4.app.LoaderManagerImpl$LoaderInfo.callOnLoadFinished(LoaderManager.java:413)
E/AndroidRuntime(29520): at android.support.v4.app.LoaderManagerImpl.initLoader(LoaderManager.java:547)
E/AndroidRuntime(29520): at com.zalzala.spellbook.SpellListView$ExpandableListCursorLoaderFragment$MyExpandableListAdapter.getChildrenCursor(SpellListView.java:217)
E/AndroidRuntime(29520): at android.widget.CursorTreeAdapter.getChildrenCursorHelper(CursorTreeAdapter.java:106)
E/AndroidRuntime(29520): at android.widget.CursorTreeAdapter.setChildrenCursor(CursorTreeAdapter.java:159)
E/AndroidRuntime(29520): at com.zalzala.spellbook.SpellListView$ExpandableListCursorLoaderFragment.onLoadFinished(SpellListView.java:183)
E/AndroidRuntime(29520): at com.zalzala.spellbook.SpellListView$ExpandableListCursorLoaderFragment.onLoadFinished(SpellListView.java:1)
E/AndroidRuntime(29520): at android.support.v4.app.LoaderManagerImpl$LoaderInfo.callOnLoadFinished(LoaderManager.java:413)
E/AndroidRuntime(29520): at android.support.v4.app.LoaderManagerImpl.initLoader(LoaderManager.java:547)
E/AndroidRuntime(29520): at com.zalzala.spellbook.SpellListView$ExpandableListCursorLoaderFragment$MyExpandableListAdapter.getChildrenCursor(SpellListView.java:217)
E/AndroidRuntime(29520): at android.widget.CursorTreeAdapter.getChildrenCursorHelper(CursorTreeAdapter.java:106)
E/AndroidRuntime(29520): at android.widget.CursorTreeAdapter.setChildrenCursor(CursorTreeAdapter.java:159)
E/AndroidRuntime(29520): at com.zalzala.spellbook.SpellListView$ExpandableListCursorLoaderFragment.onLoadFinished(SpellListView.java:183)
E/AndroidRuntime(29520): at com.zalzala.spellbook.SpellListView$ExpandableListCursorLoaderFragment.onLoadFinished(SpellListView.java:1)
E/AndroidRuntime(29520): at android.support.v4.app.LoaderManagerImpl$LoaderInfo.callOnLoadFinished(LoaderManager.java:413)
E/AndroidRuntime(29520): at android.support.v4.app.LoaderManagerImpl.initLoader(LoaderManager.java:547)
E/AndroidRuntime(29520): at com.zalzala.spellbook.SpellListView$ExpandableListCursorLoaderFragment$MyExpandableListAdapter.getChildrenCursor(SpellListView.java:217)
E/AndroidRuntime(29520): at android.widget.CursorTreeAdapter.getChildrenCursorHelper(CursorTreeAdapter.java:106)
E/AndroidRuntime(29520): at android.widget.CursorTreeAdapter.setChildrenCursor(CursorTreeAdapter.java:159)
E/AndroidRuntime(29520): at com.zalzala.spellbook.SpellListView$ExpandableListCursorLoaderFragment.onLoadFinished(SpellListView.java:183)
E/AndroidRuntime(29520): at com.zalzala.spellbook.SpellListView$ExpandableListCursorLoaderFragment.onLoadFinished(SpellListView.java:1)
E/AndroidRuntime(29520): at android.support.v4.app.LoaderManagerImpl$LoaderInfo.callOnLoadFinished(LoaderManager.java:413)
E/AndroidRuntime(29520): at android.support.v4.app.LoaderManagerImpl.initLoader(LoaderManager.java:547)
E/AndroidRuntime(29520): at com.zalzala.spellbook.SpellListView$ExpandableListCursorLoaderFragment$MyExpandableListAdapter.getChildrenCursor(SpellListView.java:217)
E/AndroidRuntime(29520): at android.widget.CursorTreeAdapter.getChildrenCursorHelper(CursorTreeAdapter.ja
W/ActivityManager( 6887): Force finishing activity com.zalzala.spellbook/.SpellListView
因此,由于某些原因,在重新打开组时会反复为子游标调用onLoadFinished().
这是我的加载程序实现:
@Override
public Loader<Cursor> onCreateLoader(int id, Bundle args) {
// TODO Auto-generated method stub
Log.d(Spellbook.TAG,"onCreateLoader for id "+id);
if (id <123456){
Uri spellUri = Uri.withAppendedPath(SpellProvider.CONTENT_URI, "class");
spellUri = Uri.withAppendedPath(spellUri, mCLASS);
spellUri = ContentUris.withAppendedId(spellUri, id);
return new CursorLoader(getActivity(), spellUri, null, null, null, null);
}else {
//get group cursor
Uri groupUri = Uri.withAppendedPath(SpellProvider.CONTENT_URI, "levels");
groupUri = Uri.withAppendedPath(groupUri, mCLASS);
return new CursorLoader(getActivity(), groupUri, null, null, null, null);
}
}
@Override
public void onl oadFinished(Loader<Cursor> loader, Cursor data) {
// TODO Auto-generated method stub
int id = loader.getId();
Log.d(Spellbook.TAG,"onLoadFinished() for id "+id);
if (id < 123456){
//child cursor
((CursorTreeAdapter) mAdapter).setChildrenCursor(id, data);
} else {
((CursorTreeAdapter) mAdapter).setGroupCursor(data);
}
}
@Override
public void onl oaderReset(Loader<Cursor> loader) {
// TODO Auto-generated method stub
int id = loader.getId();
Log.d(Spellbook.TAG,"onLoaderReset() for id "+id);
if (id < 123456){
//child cursor
((CursorTreeAdapter) mAdapter).setChildrenCursor(id, null);
} else {
((CursorTreeAdapter) mAdapter).setGroupCursor(null);
}
}
我用构造函数调用CursorTreeAdapter,该构造函数将自动重新查询指定为false.
public class MyExpandableListAdapter extends CursorTreeAdapter {
public MyExpandableListAdapter(Cursor cursor, Context context) {
super(cursor, context, false); //do not auto requery. pretty sure CursorLoader needs this.
}
@Override
protected Cursor getChildrenCursor(Cursor groupCursor) {
// Given the group, we return a cursor for all the children within that group
int id = groupCursor.getInt(groupCursor.getColumnIndex(SpellDbAdapter.KEY_LEVEL));
getLoaderManager().initLoader(id, null, ExpandableListCursorLoaderFragment.this);
return null;
}
谢谢你的帮助!
解决方法:
在onGroupCollapsed()上调用destroyLoader().但是它不能完全解决问题.看一下CursorTreeAdapter实现,请确保不要将其与CursorLoader一起使用.
扩展BaseExpandableAdapter确实更好.这种方式可以避免不必要的内容观察者使用(在使用加载程序的情况下).在我的自定义适配器中,我将以稀疏数组形式创建的加载器保留下来,并在组崩溃时销毁它们.效果很好 :)