Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/android/187.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Android ExpandableListView的SimpleCorsOrtreeAdapter和游标加载程序_Android_Simplecursoradapter_Expandablelistadapter_Android Cursorloader - Fatal编程技术网

Android ExpandableListView的SimpleCorsOrtreeAdapter和游标加载程序

Android ExpandableListView的SimpleCorsOrtreeAdapter和游标加载程序,android,simplecursoradapter,expandablelistadapter,android-cursorloader,Android,Simplecursoradapter,Expandablelistadapter,Android Cursorloader,我正试图通过使用SimpleCursorTreeAdapter public class GroupsAdapter extends SimpleCursorTreeAdapter { private final String DEBUG_TAG = getClass().getSimpleName().toString(); private ContactManager mActivity; private GroupsListFragment mFragment; //

我正试图通过使用
SimpleCursorTreeAdapter

public class GroupsAdapter extends SimpleCursorTreeAdapter {

  private final String DEBUG_TAG = getClass().getSimpleName().toString();

  private ContactManager mActivity;
  private GroupsListFragment mFragment;

  // Note that the constructor does not take a Cursor. This is done to avoid
  // querying the database on the main thread.
  public GroupsAdapter(Context context, GroupsListFragment glf,
    int groupLayout, int childLayout, String[] groupFrom,
    int[] groupTo, String[] childrenFrom, int[] childrenTo) {

    super(context, null, groupLayout, groupFrom, groupTo, childLayout,
      childrenFrom, childrenTo);
    mActivity = (ContactManager) context;
    mFragment = glf;
  }

  @Override
  protected Cursor getChildrenCursor(Cursor groupCursor) {
    // Given the group, we return a cursor for all the children within that group
    int groupId = groupCursor.getInt(groupCursor
      .getColumnIndex(ContactsContract.Groups._ID));

    Log.d(DEBUG_TAG, "getChildrenCursor() for groupId " + groupId);

    Loader loader = mActivity.getLoaderManager().getLoader(groupId); 
    if ( loader != null && loader.isReset() ) { 
      mActivity.getLoaderManager().restartLoader(groupId, null, mFragment); 
    } else { 
      mActivity.getLoaderManager().initLoader(groupId, null, mFragment); 
    } 

  }

}
下面是我的
Fragment
类,它实现了
CursorLoader

public class GroupsListFragment extends ExpandableListFragment implements
  LoaderManager.LoaderCallbacks<Cursor> {

  private final String DEBUG_TAG = getClass().getSimpleName().toString();      

  private static final String[] CONTACTS_PROJECTION = new String[] {
    ContactsContract.Contacts._ID,
    ContactsContract.Contacts.DISPLAY_NAME };  

  private static final String[] GROUPS_SUMMARY_PROJECTION = new String[] {
    ContactsContract.Groups.TITLE, ContactsContract.Groups._ID,
    ContactsContract.Groups.SUMMARY_COUNT,
    ContactsContract.Groups.ACCOUNT_NAME,
    ContactsContract.Groups.ACCOUNT_TYPE,
    ContactsContract.Groups.DATA_SET };

  GroupsAdapter mAdapter;

  @Override
  public void onActivityCreated(Bundle savedInstanceState) {
    super.onActivityCreated(savedInstanceState);

    populateContactList();

    getLoaderManager().initLoader(-1, null, this);
  } 

  public Loader<Cursor> onCreateLoader(int id, Bundle args) {
    // This is called when a new Loader needs to be created.
    Log.d(DEBUG_TAG, "onCreateLoader for loader_id " + id);
    CursorLoader cl;
    if (id != -1) {
      // child cursor
      Uri contactsUri = ContactsContract.Data.CONTENT_URI;
      String selection = "(("
        + ContactsContract.CommonDataKinds.GroupMembership.DISPLAY_NAME
        + " NOTNULL) AND ("
        + ContactsContract.CommonDataKinds.GroupMembership.HAS_PHONE_NUMBER
        + "=1) AND ("
        + ContactsContract.CommonDataKinds.GroupMembership.DISPLAY_NAME
        + " != '') AND ("
        + ContactsContract.CommonDataKinds.GroupMembership.GROUP_ROW_ID
        + " = ? ))";
      String sortOrder = ContactsContract.CommonDataKinds.GroupMembership.DISPLAY_NAME
        + " COLLATE LOCALIZED ASC";
      String[] selectionArgs = new String[] { String.valueOf(id) };

      cl = new CursorLoader(getActivity(), contactsUri,
        CONTACTS_PROJECTION, selection, selectionArgs, sortOrder);
    } else {
      // group cursor
      Uri groupsUri = ContactsContract.Groups.CONTENT_SUMMARY_URI;
      String selection = "((" + ContactsContract.Groups.TITLE
        + " NOTNULL) AND (" + ContactsContract.Groups.TITLE
        + " != '' ))";
      String sortOrder = ContactsContract.Groups.TITLE
        + " COLLATE LOCALIZED ASC";
      cl = new CursorLoader(getActivity(), groupsUri,
        GROUPS_SUMMARY_PROJECTION, selection, null, sortOrder);
    }

    return cl;
  }

  public void onLoadFinished(Loader<Cursor> loader, Cursor data) {
    // Swap the new cursor in. 
    int id = loader.getId();
    Log.d(DEBUG_TAG, "onLoadFinished() for loader_id " + id);
    if (id != -1) {
      // child cursor
      if (!data.isClosed()) {
        Log.d(DEBUG_TAG, "data.getCount() " + data.getCount());
        try {
          mAdapter.setChildrenCursor(id, data);
        } catch (NullPointerException e) {
          Log.w("DEBUG","Adapter expired, try again on the next query: "
            + e.getMessage());
        }
      }
    } else {
      mAdapter.setGroupCursor(data);
    }

  }

  public void onLoaderReset(Loader<Cursor> loader) {
    // This is called when the last Cursor provided to onLoadFinished()
    // is about to be closed.
    int id = loader.getId();
    Log.d(DEBUG_TAG, "onLoaderReset() for loader_id " + id);
    if (id != -1) {
      // child cursor
      try {
        mAdapter.setChildrenCursor(id, null);
      } catch (NullPointerException e) {
        Log.w("TAG", "Adapter expired, try again on the next query: "
          + e.getMessage());
      }
    } else {
      mAdapter.setGroupCursor(null);
    }
  }

  /**
  * Populate the contact list
  */
  private void populateContactList() {
    // Set up our adapter
    mAdapter = new GroupsAdapter(getActivity(),this,
      android.R.layout.simple_expandable_list_item_1,
      android.R.layout.simple_expandable_list_item_1,
      new String[] { ContactsContract.Groups.TITLE }, // Name for group layouts
      new int[] { android.R.id.text1 },
      new String[] { ContactsContract.Contacts.DISPLAY_NAME }, // Name for child layouts
      new int[] { android.R.id.text1 });

    setListAdapter(mAdapter);
  }
}
public class GroupsListFragment extends ExpandableListFragment implements
  LoaderManager.LoaderCallbacks<Cursor> {

  private final String DEBUG_TAG = getClass().getSimpleName().toString();      

  private static final String[] CONTACTS_PROJECTION = new String[] {
    ContactsContract.Contacts._ID,
    ContactsContract.Contacts.DISPLAY_NAME };  

  private static final String[] GROUPS_PROJECTION = new String[] {
    ContactsContract.Groups.TITLE, ContactsContract.Groups._ID };

  GroupsAdapter mAdapter;

  @Override
  public void onActivityCreated(Bundle savedInstanceState) {
    super.onActivityCreated(savedInstanceState);

    populateContactList();

    // Prepare the loader. Either re-connect with an existing one,
    // or start a new one.
    Loader loader = getLoaderManager().getLoader(-1);
    if (loader != null && !loader.isReset()) {
      getLoaderManager().restartLoader(-1, null, this);
    } else {
      getLoaderManager().initLoader(-1, null, this);
    }
  } 

  public Loader<Cursor> onCreateLoader(int id, Bundle args) {
    // This is called when a new Loader needs to be created.
    Log.d(DEBUG_TAG, "onCreateLoader for loader_id " + id);
    CursorLoader cl;
    if (id != -1) {
      // child cursor
      Uri contactsUri = ContactsContract.Data.CONTENT_URI;
      String selection = "((" + ContactsContract.Contacts.DISPLAY_NAME
        + " NOTNULL) AND ("
        + ContactsContract.Contacts.HAS_PHONE_NUMBER + "=1) AND ("
        + ContactsContract.Contacts.DISPLAY_NAME + " != '') AND ("
        + ContactsContract.CommonDataKinds.GroupMembership.GROUP_ROW_ID
        + " = ? ))";
      String sortOrder = ContactsContract.Contacts.DISPLAY_NAME
        + " COLLATE LOCALIZED ASC";
      String[] selectionArgs = new String[] { String.valueOf(id) };

      cl = new CursorLoader(getActivity(), contactsUri,
        CONTACTS_PROJECTION, selection, selectionArgs, sortOrder);
    } else {
      // group cursor
      Uri groupsUri = ContactsContract.Groups.CONTENT_URI;
      String selection = "((" + ContactsContract.Groups.TITLE
        + " NOTNULL) AND (" + ContactsContract.Groups.TITLE
        + " != '' ))";
      String sortOrder = ContactsContract.Groups.TITLE
        + " COLLATE LOCALIZED ASC";
      cl = new CursorLoader(getActivity(), groupsUri,
        GROUPS_PROJECTION, selection, null, sortOrder);
    }

    return cl;
  }

  public void onLoadFinished(Loader<Cursor> loader, Cursor data) {
    // Swap the new cursor in. 
    int id = loader.getId();
    Log.d(DEBUG_TAG, "onLoadFinished() for loader_id " + id);
    if (id != -1) {
      // child cursor
      if (!data.isClosed()) {
        Log.d(DEBUG_TAG, "data.getCount() " + data.getCount());

        HashMap<Integer,Integer> groupMap = mAdapter.getGroupMap();
        try {
          int groupPos = groupMap.get(id);
          Log.d(DEBUG_TAG, "onLoadFinished() for groupPos " + groupPos);
          mAdapter.setChildrenCursor(groupPos, data);
        } catch (NullPointerException e) {
          Log.w("DEBUG","Adapter expired, try again on the next query: "
            + e.getMessage());
        }
      }
    } else {
      mAdapter.setGroupCursor(data);
    }

  }

  public void onLoaderReset(Loader<Cursor> loader) {
    // This is called when the last Cursor provided to onLoadFinished()
    // is about to be closed.
    int id = loader.getId();
    Log.d(DEBUG_TAG, "onLoaderReset() for loader_id " + id);
    if (id != -1) {
      // child cursor
      try {
        mAdapter.setChildrenCursor(id, null);
      } catch (NullPointerException e) {
        Log.w("TAG", "Adapter expired, try again on the next query: "
          + e.getMessage());
      }
    } else {
      mAdapter.setGroupCursor(null);
    }
  }

  /**
  * Populate the contact list
  */
  private void populateContactList() {
    // Set up our adapter
    mAdapter = new GroupsAdapter(getActivity(),this,
      android.R.layout.simple_expandable_list_item_1,
      android.R.layout.simple_expandable_list_item_1,
      new String[] { ContactsContract.Groups.TITLE }, // Name for group layouts
      new int[] { android.R.id.text1 },
      new String[] { ContactsContract.Contacts.DISPLAY_NAME }, // Name for child layouts
      new int[] { android.R.id.text1 });

    setListAdapter(mAdapter);
  }
}
问题是,当我单击其中一个父组时,三种情况之一似乎以不一致的方式发生

1) 要么组打开,孩子们出现在下面

2) 该组未打开,并且
setChildrenCursor()
调用抛出一个
NullPointerException
错误,该错误在try-catch块中被捕获

3) 组未打开,并且未引发任何错误

下面是展开组并显示子级的场景中的一些调试输出:

显示所有组时,输出:

05-20 10:08:22.765: D/GroupsListFragment(22132): onCreateLoader for loader_id -1
05-20 10:08:23.613: D/GroupsListFragment(22132): onLoadFinished() for loader_id -1
-1是组游标的加载程序\u id

然后,如果我特别选择一个组(我们称之为A组),它将输出:

05-20 23:22:31.140: D/GroupsAdapter(13844): getChildrenCursor() for groupId 67
05-20 23:22:31.140: D/GroupsListFragment(13844): onCreateLoader for loader_id 67
05-20 23:22:31.254: D/GroupsListFragment(13844): onLoadFinished() for loader_id 67
05-20 23:22:31.254: D/GroupsListFragment(13844): data.getCount() 4
05-20 23:22:31.254: W/GroupsListFragment(13844): Adapter expired, try again on the next query: null
05-20 23:25:38.089: D/GroupsAdapter(13844): getChildrenCursor() for groupId 3
05-20 23:25:38.089: D/GroupsListFragment(13844): onCreateLoader for loader_id 3
05-20 23:25:38.207: D/GroupsListFragment(13844): onLoadFinished() for loader_id 3
05-20 23:25:38.207: D/GroupsListFragment(13844): data.getCount() 6
该组不展开,并捕获
NullPointerException
。然后,如果我选择另一个组(我们称之为B组),它将输出:

05-20 23:22:31.140: D/GroupsAdapter(13844): getChildrenCursor() for groupId 67
05-20 23:22:31.140: D/GroupsListFragment(13844): onCreateLoader for loader_id 67
05-20 23:22:31.254: D/GroupsListFragment(13844): onLoadFinished() for loader_id 67
05-20 23:22:31.254: D/GroupsListFragment(13844): data.getCount() 4
05-20 23:22:31.254: W/GroupsListFragment(13844): Adapter expired, try again on the next query: null
05-20 23:25:38.089: D/GroupsAdapter(13844): getChildrenCursor() for groupId 3
05-20 23:25:38.089: D/GroupsListFragment(13844): onCreateLoader for loader_id 3
05-20 23:25:38.207: D/GroupsListFragment(13844): onLoadFinished() for loader_id 3
05-20 23:25:38.207: D/GroupsListFragment(13844): data.getCount() 6
这一次,不会抛出
NullPointerException
。而不是B组扩大,A组扩大

有人能解释一下
setChildrenCursor()
调用显示的行为吗

我认为在
onCreateLoader()
中如何实例化组/子游标装入器存在问题。对于群组
CursorLoader
我只希望手机中的所有群组。子
游标加载程序
应包含组内的所有联系人。有人知道问题出在哪里吗

更新

多亏@Yam的建议,我现在修改了
getChildrenCursor()
方法。我现在选择的是groupCursor位置,而不是ContactsContract.Groups.\u ID的值,以传递到initLoader()调用中。我还将逻辑更改为仅当loader不为null且loader isReset为false时才调用restartLoader()

protected Cursor getChildrenCursor(Cursor groupCursor) {
  // Given the group, we return a cursor for all the children within that
  // group
  int groupPos = groupCursor.getPosition();
  Log.d(DEBUG_TAG, "getChildrenCursor() for groupPos " + groupPos);

  Loader loader = mActivity.getLoaderManager().getLoader(groupPos);
  if (loader != null && !loader.isReset()) {
    mActivity.getLoaderManager().restartLoader(groupPos, null, mFragment);
  } else {
    mActivity.getLoaderManager().initLoader(groupPos, null, mFragment);
  }

  return null;
}
这显然更有意义,不会表现出某个群体有时扩张而不是其他时候扩张的一些不稳定行为

但是,有些联系人显示在他们不属于的组下。还有一些组中有联系人,但不会显示任何联系人。因此,
getChildrenCursor()
问题似乎现在可以解决了

但现在看来是如何在
onCreateLoader()
方法中实例化游标加载程序的问题。对于实例化不正确的子游标,是否在
onCreateLoader()
方法中返回了
CursorLoader

更新


因此,我确定了我的一个问题。在
getChildrenCursor()
方法中,如果我将groupId传递到
initLoader()
方法中,那么在
onCreateLoader()
方法中,当创建
CursorLoader
时,它将为查询获取正确的groupId参数。但是,在
onLoadFinished()
中,对
setChildrenCursor()
的调用传递的是第一个参数的加载程序id,而不是groupPosition。我猜我必须将加载器ID映射到某些数据结构中的组位置。但我不确定这是否是最好的方法。有人有什么建议吗?

我使用ExpandableListView的经验不好。它在不同Android版本中的行为是不同的。如果你还没有深入研究它,你可能会考虑重新设计你的界面。 无论如何,对于你的问题,我建议你回顾一下这三点

首先,在对init的调用中,使用子游标加载器

mActivity.getLoaderManager().initLoader(groupId, null, mFragment); 
传入的groupId是ContactsContract.Groups.\u ID的值。然后,在setChildrenCursor的第一个参数中使用此ID。这可能是错误的。 不要将groupId传递到initLoader中,而是尝试传递组游标位置。例如:

int iGroupPos = groupCursor.getPosition();
if ( loader != null && !loader.isReset())
    mActivity.getLoaderManager().restartLoader(iGroupPos, null, mFragment); 
else
    mActivity.getLoaderManager().initLoader(iGroupPos, null, mFragment); 
其次,您可以看到,在我上面建议的代码中,您可能应该仅在loader不为null且loader isReset为false时调用restartLoader

protected Cursor getChildrenCursor(Cursor groupCursor) {
  // Given the group, we return a cursor for all the children within that
  // group
  int groupPos = groupCursor.getPosition();
  Log.d(DEBUG_TAG, "getChildrenCursor() for groupPos " + groupPos);

  Loader loader = mActivity.getLoaderManager().getLoader(groupPos);
  if (loader != null && !loader.isReset()) {
    mActivity.getLoaderManager().restartLoader(groupPos, null, mFragment);
  } else {
    mActivity.getLoaderManager().initLoader(groupPos, null, mFragment);
  }

  return null;
}

第三,您需要为getChildrenCursor调用返回一个值,我认为该值可能为null。

因此我发现需要将LoaderID映射到groupPositions,这解决了我的问题:

下面是我的
Fragment
类,它实现了
CursorLoader

public class GroupsListFragment extends ExpandableListFragment implements
  LoaderManager.LoaderCallbacks<Cursor> {

  private final String DEBUG_TAG = getClass().getSimpleName().toString();      

  private static final String[] CONTACTS_PROJECTION = new String[] {
    ContactsContract.Contacts._ID,
    ContactsContract.Contacts.DISPLAY_NAME };  

  private static final String[] GROUPS_SUMMARY_PROJECTION = new String[] {
    ContactsContract.Groups.TITLE, ContactsContract.Groups._ID,
    ContactsContract.Groups.SUMMARY_COUNT,
    ContactsContract.Groups.ACCOUNT_NAME,
    ContactsContract.Groups.ACCOUNT_TYPE,
    ContactsContract.Groups.DATA_SET };

  GroupsAdapter mAdapter;

  @Override
  public void onActivityCreated(Bundle savedInstanceState) {
    super.onActivityCreated(savedInstanceState);

    populateContactList();

    getLoaderManager().initLoader(-1, null, this);
  } 

  public Loader<Cursor> onCreateLoader(int id, Bundle args) {
    // This is called when a new Loader needs to be created.
    Log.d(DEBUG_TAG, "onCreateLoader for loader_id " + id);
    CursorLoader cl;
    if (id != -1) {
      // child cursor
      Uri contactsUri = ContactsContract.Data.CONTENT_URI;
      String selection = "(("
        + ContactsContract.CommonDataKinds.GroupMembership.DISPLAY_NAME
        + " NOTNULL) AND ("
        + ContactsContract.CommonDataKinds.GroupMembership.HAS_PHONE_NUMBER
        + "=1) AND ("
        + ContactsContract.CommonDataKinds.GroupMembership.DISPLAY_NAME
        + " != '') AND ("
        + ContactsContract.CommonDataKinds.GroupMembership.GROUP_ROW_ID
        + " = ? ))";
      String sortOrder = ContactsContract.CommonDataKinds.GroupMembership.DISPLAY_NAME
        + " COLLATE LOCALIZED ASC";
      String[] selectionArgs = new String[] { String.valueOf(id) };

      cl = new CursorLoader(getActivity(), contactsUri,
        CONTACTS_PROJECTION, selection, selectionArgs, sortOrder);
    } else {
      // group cursor
      Uri groupsUri = ContactsContract.Groups.CONTENT_SUMMARY_URI;
      String selection = "((" + ContactsContract.Groups.TITLE
        + " NOTNULL) AND (" + ContactsContract.Groups.TITLE
        + " != '' ))";
      String sortOrder = ContactsContract.Groups.TITLE
        + " COLLATE LOCALIZED ASC";
      cl = new CursorLoader(getActivity(), groupsUri,
        GROUPS_SUMMARY_PROJECTION, selection, null, sortOrder);
    }

    return cl;
  }

  public void onLoadFinished(Loader<Cursor> loader, Cursor data) {
    // Swap the new cursor in. 
    int id = loader.getId();
    Log.d(DEBUG_TAG, "onLoadFinished() for loader_id " + id);
    if (id != -1) {
      // child cursor
      if (!data.isClosed()) {
        Log.d(DEBUG_TAG, "data.getCount() " + data.getCount());
        try {
          mAdapter.setChildrenCursor(id, data);
        } catch (NullPointerException e) {
          Log.w("DEBUG","Adapter expired, try again on the next query: "
            + e.getMessage());
        }
      }
    } else {
      mAdapter.setGroupCursor(data);
    }

  }

  public void onLoaderReset(Loader<Cursor> loader) {
    // This is called when the last Cursor provided to onLoadFinished()
    // is about to be closed.
    int id = loader.getId();
    Log.d(DEBUG_TAG, "onLoaderReset() for loader_id " + id);
    if (id != -1) {
      // child cursor
      try {
        mAdapter.setChildrenCursor(id, null);
      } catch (NullPointerException e) {
        Log.w("TAG", "Adapter expired, try again on the next query: "
          + e.getMessage());
      }
    } else {
      mAdapter.setGroupCursor(null);
    }
  }

  /**
  * Populate the contact list
  */
  private void populateContactList() {
    // Set up our adapter
    mAdapter = new GroupsAdapter(getActivity(),this,
      android.R.layout.simple_expandable_list_item_1,
      android.R.layout.simple_expandable_list_item_1,
      new String[] { ContactsContract.Groups.TITLE }, // Name for group layouts
      new int[] { android.R.id.text1 },
      new String[] { ContactsContract.Contacts.DISPLAY_NAME }, // Name for child layouts
      new int[] { android.R.id.text1 });

    setListAdapter(mAdapter);
  }
}
public class GroupsListFragment extends ExpandableListFragment implements
  LoaderManager.LoaderCallbacks<Cursor> {

  private final String DEBUG_TAG = getClass().getSimpleName().toString();      

  private static final String[] CONTACTS_PROJECTION = new String[] {
    ContactsContract.Contacts._ID,
    ContactsContract.Contacts.DISPLAY_NAME };  

  private static final String[] GROUPS_PROJECTION = new String[] {
    ContactsContract.Groups.TITLE, ContactsContract.Groups._ID };

  GroupsAdapter mAdapter;

  @Override
  public void onActivityCreated(Bundle savedInstanceState) {
    super.onActivityCreated(savedInstanceState);

    populateContactList();

    // Prepare the loader. Either re-connect with an existing one,
    // or start a new one.
    Loader loader = getLoaderManager().getLoader(-1);
    if (loader != null && !loader.isReset()) {
      getLoaderManager().restartLoader(-1, null, this);
    } else {
      getLoaderManager().initLoader(-1, null, this);
    }
  } 

  public Loader<Cursor> onCreateLoader(int id, Bundle args) {
    // This is called when a new Loader needs to be created.
    Log.d(DEBUG_TAG, "onCreateLoader for loader_id " + id);
    CursorLoader cl;
    if (id != -1) {
      // child cursor
      Uri contactsUri = ContactsContract.Data.CONTENT_URI;
      String selection = "((" + ContactsContract.Contacts.DISPLAY_NAME
        + " NOTNULL) AND ("
        + ContactsContract.Contacts.HAS_PHONE_NUMBER + "=1) AND ("
        + ContactsContract.Contacts.DISPLAY_NAME + " != '') AND ("
        + ContactsContract.CommonDataKinds.GroupMembership.GROUP_ROW_ID
        + " = ? ))";
      String sortOrder = ContactsContract.Contacts.DISPLAY_NAME
        + " COLLATE LOCALIZED ASC";
      String[] selectionArgs = new String[] { String.valueOf(id) };

      cl = new CursorLoader(getActivity(), contactsUri,
        CONTACTS_PROJECTION, selection, selectionArgs, sortOrder);
    } else {
      // group cursor
      Uri groupsUri = ContactsContract.Groups.CONTENT_URI;
      String selection = "((" + ContactsContract.Groups.TITLE
        + " NOTNULL) AND (" + ContactsContract.Groups.TITLE
        + " != '' ))";
      String sortOrder = ContactsContract.Groups.TITLE
        + " COLLATE LOCALIZED ASC";
      cl = new CursorLoader(getActivity(), groupsUri,
        GROUPS_PROJECTION, selection, null, sortOrder);
    }

    return cl;
  }

  public void onLoadFinished(Loader<Cursor> loader, Cursor data) {
    // Swap the new cursor in. 
    int id = loader.getId();
    Log.d(DEBUG_TAG, "onLoadFinished() for loader_id " + id);
    if (id != -1) {
      // child cursor
      if (!data.isClosed()) {
        Log.d(DEBUG_TAG, "data.getCount() " + data.getCount());

        HashMap<Integer,Integer> groupMap = mAdapter.getGroupMap();
        try {
          int groupPos = groupMap.get(id);
          Log.d(DEBUG_TAG, "onLoadFinished() for groupPos " + groupPos);
          mAdapter.setChildrenCursor(groupPos, data);
        } catch (NullPointerException e) {
          Log.w("DEBUG","Adapter expired, try again on the next query: "
            + e.getMessage());
        }
      }
    } else {
      mAdapter.setGroupCursor(data);
    }

  }

  public void onLoaderReset(Loader<Cursor> loader) {
    // This is called when the last Cursor provided to onLoadFinished()
    // is about to be closed.
    int id = loader.getId();
    Log.d(DEBUG_TAG, "onLoaderReset() for loader_id " + id);
    if (id != -1) {
      // child cursor
      try {
        mAdapter.setChildrenCursor(id, null);
      } catch (NullPointerException e) {
        Log.w("TAG", "Adapter expired, try again on the next query: "
          + e.getMessage());
      }
    } else {
      mAdapter.setGroupCursor(null);
    }
  }

  /**
  * Populate the contact list
  */
  private void populateContactList() {
    // Set up our adapter
    mAdapter = new GroupsAdapter(getActivity(),this,
      android.R.layout.simple_expandable_list_item_1,
      android.R.layout.simple_expandable_list_item_1,
      new String[] { ContactsContract.Groups.TITLE }, // Name for group layouts
      new int[] { android.R.id.text1 },
      new String[] { ContactsContract.Contacts.DISPLAY_NAME }, // Name for child layouts
      new int[] { android.R.id.text1 });

    setListAdapter(mAdapter);
  }
}

在本例中,我使用initLoader(或restartLoader)的第一个参数给出回调的组位置,并使用Bundle在getChildrenCursor中获取子数据

喜欢跟随

public class ExpandableListAdapter extends SimpleCursorTreeAdapter implements LoaderManager.LoaderCallbacks<Cursor> {
    private Context mContext;
    private LoaderManager mManager;

    public ExpandableListAdapter(
            Context context, ExpandableListAdapterListener listener, LoaderManager manager, Cursor groupCursor,
            int groupLayout, String[] groupFrom, int[] groupTo,
            int childLayout, String[] childFrom, int[] childTo) {
        super(context, groupCursor, groupLayout, groupFrom, groupTo, childLayout, childFrom, childTo);
        mContext  = context;
        mManager  = manager;
    }
    @Override
    protected Cursor getChildrenCursor(Cursor groupCursor) {
        final long idGroup = groupCursor.getLong(groupCursor.getColumnIndex("_id"));
        Bundle bundle = new Bundle();
        bundle.putLong("idGroup", idGroup);
        int groupPos = groupCursor.getPosition();
        if (mManager.getLoader(groupPos) != null && !mManager.getLoader(groupPos).isReset()) {
            mManager.restartLoader(groupPos, bundle, this);
        }
        else {
            mManager.initLoader(groupPos, bundle, this);
        }
        return null;
    }
    @Override
    public Loader<Cursor> onCreateLoader(int groupPos, Bundle bundle) {
        long idGroup = bundle.getLong("idGroup");
        return new CursorLoader(
                mContext,
                Provider.URI,
                new String[]{Table.ID, Table.ID_GROUP, Table.TITLE, Table.CONTEXT},
                Table.ID_GROUP + " = ?",
                new String[]{String.valueOf(idGroup)},
                Table.CREATED + " DESC"
        );
    }
    @Override
    public void onLoadFinished(Loader<Cursor> loader, Cursor cursor) {
        setChildrenCursor(loader.getId(), cursor);
    }
    @Override
    public void onLoaderReset(Loader<Cursor> loader) {
    }
}
公共类ExpandableListAdapter扩展SimpleCorSortreeAdapter实现LoaderManager.LoaderCallbacks{
私有上下文;
专用装载机管理器mManager;
公共可扩展列表适配器(
上下文、可扩展ListAdapterListener侦听器、LoaderManager、游标组游标、,
int-groupLayout,字符串[]groupFrom,int[]groupTo,
int childLayout,字符串[]childFrom,int[]childTo){
超级(上下文、groupCursor、groupLayout、groupFrom、groupTo、childLayout、childFrom、childTo);
mContext=上下文;
mManager=经理;
}
@凌驾
受保护的游标getChildrenCursor(游标组游标){
final long idGroup=groupCursor.getLong(groupCursor.getColumnIndex(“_id”);
Bundle=新Bundle();
bundle.putLong(“idGroup”,idGroup);
int groupPos=groupCursor.getPosition();
if(mManager.getLoader(groupPos)!=null&&!mManager.getLoader(groupPos.isReset()){
mManager.restartLoader(groupPos、bundle、this);
}
否则{
initLoader(groupPos、bundle、this);
}
返回null;
}
@凌驾
公共加载程序oncreate