gpt4 book ai didi

android - CursorLoader 和 CursorTreeAdapter

转载 作者:太空狗 更新时间:2023-10-29 12:55:25 26 4
gpt4 key购买 nike

我正在尝试将 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): onLoadFinished() 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): onLoadFinished() for id 3

这里一切都很好。到目前为止,我已经打开了 Activity 并打开了第 3 组。如果我关闭第 3 组并再次打开它,会发生以下情况:

D/SpellBook(29520): onLoadFinished() for id 3 
D/SpellBook(29520): onLoadFinished() for id 3
D/SpellBook(29520): onLoadFinished() for id 3
D/SpellBook(29520): onLoadFinished() for id 3
D/SpellBook(29520): onLoadFinished() for id 3
(... and a lot more of these)
E/AndroidRuntime(29520): FATAL EXCEPTION: main
E/AndroidRuntime(29520): java.lang.StackOverflowError
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 onLoadFinished(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 onLoaderReset(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);
}

}

我使用将自动重新查询指定为 false 的构造函数调用 CursorTreeAdapter。

    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;
}

感谢您的帮助!

最佳答案

这是一个老问题,但仍然没有正确答案(现在有)。

MyExpandableListAdapter 有一个 getChildrenCursor(Cursor) 方法:

@Override
protected Cursor getChildrenCursor(Cursor groupCursor) {
int id = groupCursor.getInt(groupCursor.getColumnIndex(SpellDbAdapter.KEY_LEVEL));
getLoaderManager().initLoader(id, null, ExpandableListCursorLoaderFragment.this);
return null;
}

该方法通过调用 initLoader 来启动 Loader。加载数据后,将调用 onLoadFinished 并设置子游标:

@Override
public void onLoadFinished(Loader<Cursor> loader, Cursor data) {
// some code
((CursorTreeAdapter) mAdapter).setChildrenCursor(id, data);
// some more code
}

CursorTreeAdapter.setChildrenCursor 方法是这样的:

public void setChildrenCursor(int groupPosition, Cursor childrenCursor) {
MyCursorHelper childrenCursorHelper = getChildrenCursorHelper(groupPosition);
childrenCursorHelper.changeCursor(childrenCursor, false);
}

它通过调用 CursorTreeAdapter.getChildrenCursorHelper 来检索 childrenCursorHelper:

synchronized MyCursorHelper getChildrenCursorHelper(int groupPosition, boolean requestCursor) {
MyCursorHelper cursorHelper = mChildrenCursorHelpers.get(groupPosition);

if (cursorHelper == null) {
if (mGroupCursorHelper.moveTo(groupPosition) == null) return null;

final Cursor cursor = getChildrenCursor(mGroupCursorHelper.getCursor());
cursorHelper = new MyCursorHelper(cursor);
mChildrenCursorHelpers.put(groupPosition, cursorHelper);
}

return cursorHelper;
}

在某些情况下,childrenCursorHelper 尚不存在,该方法现在调用 getChildrenCursor(Cursor),这是启动整个调用链的方法。从逻辑上讲,我们会遇到 StackOverflowError。

这是 CursorTreeAdapter 类中的错误。虽然其他人建议改为使用 BaseExpandableAdapter,但我建议创建自定义 CursorTreeAdapter 类并进行必要的更改和修复。

通过更改 getChildrenCursorHelper 方法可以轻松修复 StackOverflowError。首先创建 MyCursorHelper,将其添加到 mChildrenCursorHelpers,然后如果 retrieveChildCursor 设置为 true(新参数)则检索子游标。从 setChildrenCursor 调用方法意味着我们传递 false 以不进入无休止的递归。

synchronized MyCursorHelper getChildrenCursorHelper(int groupPosition, boolean retrieveChildCursor) {
MyCursorHelper cursorHelper = mChildrenCursorHelpers.get(groupPosition);

if (cursorHelper == null && mGroupCursorHelper.moveTo(groupPosition) != null) {
cursorHelper = new MyCursorHelper(null);
mChildrenCursorHelpers.put(groupPosition, cursorHelper);

if (retrieveChildCursor) {
final Cursor cursor = getChildrenCursor(mGroupCursorHelper.getCursor());
if (cursor != null) {
cursorHelper.changeCursor(cursor, false);
}
}
}

return cursorHelper;
}

同时删除 MyCursorHelper.deactivate 方法中的代码,因为 CursorLoader 负责关闭过时的游标。

关于android - CursorLoader 和 CursorTreeAdapter,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/7277038/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com