Search code examples
androideventsfilteradapterlooper

Android: execute pending event immediately?


I have a spinner that filters an adapter in OnItemSelected. Like this:

@Override
public void onItemSelected(AdapterView<?> av, View v, int position, long id) {
    switch (av.getId()) {
    case R.id.spfilteroptions:
        adapter.getFilter().refresh(); // <- what this post is about
        break;
    }
}

So now I want to do:

spinner.setSelection(...)

then as the next instruction I do:

listView.setItemChecked(adapter.getPosition(item), true);

The second instruction relies on onItemSelected callback having already done its filtering operation, because getPosition returns the correct value only after the filter is applied (obviously)

So I figure this code is not optimal since

adapter.getFilter().refresh();

is done in the background and listView.setItemChecked(position, true) is of course called before it is finished filtering.

So I do this:

adapter.ignoreFilteringRequests(true) // my own method in the adapter that results in ignoring filter() requests
spinner.setSelection(...) // now onItemSelected callback should not trigger filtering...
adapter.ignoreFilteringRequests(false)
// now I have this instead:
adapter.getFilter().filter(myContraint, new Filter.FilterListener(){ 
   @Override
    public void onFilterComplete(int count) {
        listView.setItemChecked(adapter.getPosition(item), true);
    }

})

I notice that onItemSelected is not called immediately after spinner.setSelection(...), but some time later. This causes filter() in the onItemSelected callback to be executing too, regardless of adapter.ignoreFilteringRequests() (that was set to false again after setSelection()). What is causing this, and how can I avoid this? I was thinking it may have to do with the message queue of the UI thread not executing immediately and because of this onItemSelected is not called immediately either. If that is the case, how do I cause the message queue (looper?) to process all pending events immediately before moving on?

Is there any more elegant solution to this I may have overlooked?


Solution

  • I was thinking it may have to do with the message queue of the UI thread not executing immediately and because of this onItemSelected is not called immediately either.

    Correct, more or less. Your call to setSelection() will trigger onItemSelected(), when this is all handled by the queue and main application thread.

    If that is the case, how do I cause the message queue (looper?) to process all pending events immediately before moving on?

    You don't.

    Is there any more elegant solution to this I may have overlooked?

    You should be able to wrap listView.setItemChecked(adapter.getPosition(item), true); in a Runnable and add it to the queue via a call to post() (available on any View). That should cause the aforementioned code to be run after onItemSelected() has processed.