CursorTreeAdapter with search implementation

What you should to do is extend FilterQueryProvider. This provides a runQuery() function that returns a new cursor of filtered results (likely accomplished with a database query).

In your CursorTreeAdapter adapter implementation you will then use the setFilterQueryProvider() method to provide it an instance of your FilterQueryProvider.

Finally, when you want to perform filtering you will call mAdapter.getFilter().filter("c").

However seeing as you are not actually using the SearchView autocomplete features and instead populating your own list, your chosen solution is quite a bit more complicated than it needs to be. Why don't you instead drop the Content Provider and CursorTreeAdapter and use a more simple in-memory scheme of lists or maps to back your adapter? Populate the in-memory data as required (can your entire dataset fit in memory?).


I've looked into your issue, and unfortunately I don't have time to replicate your setup. In generic terms, however, You should be able to save your constraint, and then in 'getChildrenCursor', run a query against that constraint:

Cursor getChildrenCursor(Cursor groupCursor) {
  if (mConstraint == null || mConstraint.isEmpty()) {
    // Normal query
  } else {
    // Constrained query
  }

}

I'm not certain, but I'm pretty sure that getChildrenCursor() will get called in response to a change of the parent cursor when you return the cursor in the filterQueryProvider(). You then just manage the null/filled state of the constraint.

Details:

In your filterList function, instead of doing a complicated procedure, just call runQueryOnBackgroundThread(constraint);. This will automatically offload database work to the background. Save your constraint in your filterQueryProvider:

String s = '%' + constraint.toString() + '%';
mConstraint = s;

For the query, it just depends on what you're trying to get out of the database - a quick adjustment to the code you posted runs the query like so:

String selection = ContactsContract.CommonDataKinds.Email.DATA
    + " NOT LIKE ''";
if (constraint != null) {
    selection += " AND " + ContactsContract.CommonDataKinds.Email.DATA + " LIKE ?";
}
cl = new CursorLoader(getApplicationContext(), 
    ContactsContract.CommonDataKinds.Email.CONTENT_URI,
    PROJECTION, selection, constraint, sortOrder);

The one thing I'm not too sure about is the auto expand thing you have going, My filter works but you need to collapse and open the list again to see the change.