ListView: filtering via Filterable vs. restarting CursorLoader with new URI

天涯浪子 提交于 2019-12-07 14:05:03

问题


The ListView implements methods for filtering the content. Can you elaborate on when it should be used?

As I understand it, that kind of filtering is suitable for the array based adapter -- all data already is in memory. This way, the filter just helps to skip the data that should not be displayed.

However, if the ListView is used with a cursor adapter (SQLite database) for displayig a lot of items, the data may not be in memory. On the other hand, the filter value can be embed in the SQL query to get the reduced data set effectively.

Was the filtering mechanism for ListView designed also for the cursor based data? When the Filterable should be used and when filter should be passed to the SQL query without using ListView filters? Are there any recommendations when this or that approach should be used?

Thanks

P.S. The question was separated from How the system of URIs should be designed? that combined the two earlier.


回答1:


Was the filtering mechanism for ListView designed also for the cursor based data?

The filtering mechanism through the Filter class was implemented for the adapter(a logical action to do with an adapter), the ListView is just a simple user of that adapter.

When the Filterable should be used and when filter should be passed to the SQL query without using ListView filters? Are there any recommendations when this or that approach should be used?

I don't think there are any recommendation on which one to use(or I didn't see them myself). The Filter class however is specially designed to optimize the filtering process(for example if the initial filtering operation takes some time and the user makes other requests in this time, then the Filter class will only perform the last filtering operation scheduled(the other wouldn't make sense to do)). To my shame, I don't know if the CursorLoader will cancel a load if the onLoaderReset() callback is called in that time, if it doesn't do this it would be bad because you'll do all of them(if the user makes the filtering after abcd fast, you wouldn't want to do a b c d, you'd want to do a d). You could optimize that but the hassle vs a filter wouldn't make sense.

However, if the ListView is used with a cursor adapter (SQLite database) for displayig a lot of items, the data may not be in memory. On the other hand, the filter value can be embed in the SQL query to get the reduced data set effectively.

Measure stuff. Making new queries with a bigger constraint will reduce the data set at the cost of the user seeing the result slower. If the time is unacceptable maybe it would make better sense to make a single query(for the initial constraint) and then filter that data set without additional sqlite queries.




回答2:


You can have the benefit of both. Set up the Filter but in the runQuery() of your FilterQueryProvider, don't run a completely new query against the database. Just use a wrapper around the original cursor to filter out what you don't need. This wrapper is rather straightforward to create, it was mentioned on SO as well.

Out of recent experience: don't use both. Filterable does its own background processing, so if you use it, there is no need for any CursorLoader at all. It doesn't do real harm to use both, actually, but results in unnecessary queries and slower performance. Your runQuery() query should handle both cases, unfiltered (constraint is empty) and filtered (constraint not empty), meaning that all query operations run through the filter and only the filter. All you have to do to start it is to call this in your adapter's constructor:

setFilterQueryProvider(this);
getFilter().filter(null);

And a nasty surprise that caused me some headache. CusorLoader manages the cursor rather nicely, even in strict mode, there are no problems but with Filterable, the situation is less perfect. No problems in normal operation, it does dispose of the old cursor but activity lifecycle changes can catch it out. The solution I found is to extend your ListView/RecyclerView views that you use with these adapters and make sure the cursor is destroyed in the end:

@Override
protected void onDetachedFromWindow() {
  super.onDetachedFromWindow();
  ((CursorAdapter) getAdapter()).changeCursor(null);
}

As an alternative, if you don't want to extend, you can call the same from your activity's onDestroy() for every adapter-backed view but I prefer the set-it-and-forget-it approach the first one offers.



来源:https://stackoverflow.com/questions/18144428/listview-filtering-via-filterable-vs-restarting-cursorloader-with-new-uri

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!