Это старый вопрос, но до сих пор нет правильного ответа (ну, теперь он есть).
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;
}
Метод запускает Loader с помощью вызова initLoader. После загрузки данных будет вызван 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);
}
Возвращает childrenCursorHelper с вызовом CursorTreeAdapter.getChildrenCursorHelper:
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 и внести необходимые изменения и исправления.
Ошибка StackOverflowError может быть легко исправлена путем изменения метода getChildrenCursorHelper. Сначала создайте 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 заботится о закрытии устаревших курсоров.