Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add support for observing the current state of filtering #507

Closed
magneticflux- opened this issue Dec 13, 2017 · 6 comments
Closed

Add support for observing the current state of filtering #507

magneticflux- opened this issue Dec 13, 2017 · 6 comments

Comments

@magneticflux-
Copy link
Contributor

Since I have a large list with complex filtering rules, filtering operations may take a second or two to complete. I wish to show an indeterminate progress bar to indicate to users that the operation is indeed working, but there is no listener that is fired when the loading state changes. Currently, I set the progress bar to View.VISIBLE whenever I update or filter any data AND the adapter has search text, and set it to View.GONE whenever the adapter's OnUpdateListener is triggered.

@davideas
Copy link
Owner

@magneticflux- thanks for the message. But what do you want to achieve?
An intermediate state of the searching? because the start and the ending you have already.

PS. In my demoApp I show the swipeRefresh to indicate the searching and the update.

@magneticflux-
Copy link
Contributor Author

@davideas It appears that this is the code that triggers the SnackBar with the elapsed filtering time after a filter or refresh is completed:

    @Override
    public void onUpdateEmptyView(int size) {
            ...
            String message = (mAdapter.hasSearchText() ? "Filtered " : "Refreshed ");
            message += size + " items in " + mAdapter.getTime() + "ms";
            Snackbar.make(findViewById(R.id.main_view), message, Snackbar.LENGTH_SHORT).show();
            ...
    }

While the method of checking hasSearchText() works for this particular case, it isn't as idiomatic as I would like and requires listening to all updates, not just filtering ones. I overrode FlexibleAdapter to try to implement this myself using the filterItems and onPostFilter methods, but the onPostFilter method is not called when the mNotifications list is null, which is the case when there is no search text.

I would ultimately like a way to listen to filter requests without any fast-fail optimizations, i.e. every filterX call results in at least one onFilter callback.

@davideas
Copy link
Owner

@magneticflux-, if I understood well your intention is to separate the updates from the filter results having 2 callbacks respectively? However:

  • onPostFilter is always called if filter text has changed.
  • mNotifications is null when there's no animation, when updateDataSet is called.

@davideas
Copy link
Owner

This enhancement will be part of #439, new feature to update empty Views.

@magneticflux-
Copy link
Contributor Author

@davideas Thanks for the response! Unfortunately, I don't think your fix resolves my issue completely. The onPostFilter is still only called when items move around, but there is no way for me to predict before I start a filter if items will be moved, i.e. I should start showing the progress bar. I love the fact that updating and filtering are asynchronous, but it's difficult to use when there aren't many callbacks for all results of asynchronous operations.

    @Override
    protected void onPostExecute(Void result) {
        if (mNotifications != null) { // <-------------------- (Only true if items move)
            //Execute post data
            switch (what) {
                case UPDATE:
                    // Notify all the changes
                    executeNotifications(Payload.CHANGE);
                    onPostUpdate();
                    break;
                case FILTER:
                    // Notify all the changes
                    executeNotifications(Payload.FILTER);
                    onPostFilter(); // <-------------------- (Callback after a filter triggers)
                    break;
            }
        }
        mFilterAsyncTask = null;
    }

To keep everything backwards-compatible, you could deprecate your listeners and instead expose LiveData properties from Android Lifecycles or Observable properties from RxJava. That way, uses could listen for changes in the adapter's state, which they could then act on in a clearer manner.

@davideas
Copy link
Owner

davideas commented Dec 26, 2017

@magneticflux- The progress bar should be visible every time user modifies the search text and hidden at the end of the process. onPostFilter is always called in case search text changes: all modifications use granular notifications.
If you don't use normal text to filter, then you need a special filter that in the end brings you to update the content with updateDataSet (need to create new methods to filter items with a "filter object").

Note that mNotifications is null only in case notifyDataSetChanged is invoked, more precisely when updateDataSet is invoked without animations parameter, in other cases is never null.
The filter is always local based on the search text; the initial list is preserved internally; you can always provide a new list to filter.

To use LiveData in this context, the adapter needs a deep change, since the base library should not depend by those objects. At the moment, there's a Livedata extension that is designed to receive model items from any repository and forward adapter items to the adapter, normally an updateDataSet should be invoked providing a new initial list.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

2 participants