- c - 在位数组中找到第一个零
- linux - Unix 显示有关匹配两种模式之一的文件的信息
- 正则表达式替换多个文件
- linux - 隐藏来自 xtrace 的命令
我正在尝试将 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/
我正在申请 android我使用 CursorTreeAdapter 作为 ExpandableListView。我想使用搜索框来显示过滤后的 ExpandableListView 项目。像这样: 这
尝试使用 ExpandableListView 和 CursorTreeAdapter。这里引用 Android 手册: protected 抽象游标 getChildrenCursor(游标组游标)
我想我没有正确理解如何使用 CursorTreeAdapter.setChildrenCursor() ,因为我得到一个 StackOverflowError,因为我的 LogCat 中似乎有一个循环
我正在尝试将 CursorLoader 与 CursorTreeAdapter 一起使用,但遇到了一个我无法弄清楚的问题。 (如果你有这样的工作示例,请随意跳过其余部分并将其附在下面。我将非常感激)第
我目前正在使用 CursorTreeAdapter 将 Curser 映射到 Android 中的 ExpandableListView。 除了在 ListView 中处理数据的方式外,一切正常。通常
我已经为我从 CursorTreeAdapter 扩展的 ExpandableListView 实现了自定义适配器类(class)。一切都按预期工作。 但我想知道在 getChildrenCursor
这是我的 Activity 代码: public class MenuActivity extends FragmentActivity implements ActionBar.TabLis
我试图从我的数据库中获取不同游标中的数据,并将其显示在按组分隔的 ExpandableListView 中。像下面这样: 历史任务(到光标 0) 历史 1 历史 2 地理任务(到光标 1) 地理 1
我是一名优秀的程序员,十分优秀!