The SearchView.OnQueryTextListener method, onQuery

2019-07-14 04:33发布

问题:

The SearchView.OnQueryTextListener method, onQueryTextChange, fires when onPrepareOptionsMenu is called after I invoke invalidateOptionsMenu().

My SearchView OnQueryTextListener..

final private SearchView.OnQueryTextListener queryListener = new SearchView.OnQueryTextListener() {

  @Override
  public boolean onQueryTextChange(String newText) {
    loaderID = 1;
    Bundle args = new Bundle();
    args.putInt("loaderID", loaderID);
    if(!TextUtils.isEmpty(newText)){
      uri = Uri.parse(DataProvider.URIPREPEND + DataProvider.SEARCH + "/?" + newText);
      Log.d("D", "onQueryTextChange() Search URI: " + uri.toString());
    }
    args.putParcelable("uri", uri);
    try{
      Log.d("D", "onQueryTextChange() case: search");
      fragment.onMessage(args);
    }catch (ClassCastException cce){

    }
    return false;
  }
  @Override
  public boolean onQueryTextSubmit(String query) {
    // Toast.makeText(getActivity(), "Searching for: " + query + "...", Toast.LENGTH_SHORT).show();
    return false;
  }
};

It gets called every time I invoke invalidateOptionsMenu() from within onOptionsItemSelected()..

@Override
public boolean onOptionsItemSelected(MenuItem item) {
  Bundle args;
  switch (item.getItemId()) {
    case android.R.id.home:
      uri = Uri.parse(DataProvider.URIPREPEND + DataProvider.BOOKMARKS);
      loaderID = 0;
      args = new Bundle();
      args.putParcelable("uri", uri);
      args.putInt("loaderID", loaderID);
      try{
        Log.d("D", "onOptionsItemSelected() case: home");
        fragment.onMessage(args);
        invalidateOptionsMenu();
      }catch (ClassCastException cce){

      }
      return true;
    default:
      return super.onOptionsItemSelected(item);
  }
}

I manage the SearchView in onCreateOptionsMenu() which is called once, to my understanding. I am confused how onPrepareOptionsMenu() could make the onQueryTextChange in my textListener to get called.

@Override
public boolean onCreateOptionsMenu(Menu menu) {
  // Inflate the menu; this adds items to the action bar if it is present.
  getMenuInflater().inflate(R.menu.menu, menu);
  // Associate searchable configuration with the SearchView
  SearchManager searchManager = (SearchManager) getSystemService(Context.SEARCH_SERVICE);
  SearchView searchView = (SearchView) menu.findItem(R.id.searchactionbaritem).getActionView();
  //searchView.setSearchableInfo(searchManager.getSearchableInfo(getComponentName()));
  searchView.setOnQueryTextListener(queryListener);

  return super.onCreateOptionsMenu(menu);
}

@Override
public boolean onPrepareOptionsMenu(Menu menu){
  menu.setGroupEnabled(R.id.browse_group, true);
  menu.setGroupVisible(R.id.browse_group, true);
  menu.setGroupEnabled(R.id.recipe_group, false);
  menu.setGroupVisible(R.id.recipe_group, false);
  // home
  if (loaderID == 0) {
    Log.d("D", "mListFragment/onPrepareOptionsMenu() home");
    menu.findItem(android.R.id.home).setEnabled(false).setIcon(R.drawable.ic_home_black_48dp);
    menu.findItem(R.id.browse).setEnabled(true).setIcon(R.drawable.ic_browse_all_white_48dp);
  } else { // browse_all or search
    if(uri.getQuery() != null){ // search
      Log.d("D", "mListFragment/onPrepareOptionsMenu() search");
      menu.findItem(android.R.id.home).setEnabled(true).setIcon(R.drawable.ic_home_white_48dp);
      menu.findItem(R.id.browse).setEnabled(true).setIcon(R.drawable.ic_browse_all_white_48dp);
    }else{ // browse_all
      Log.d("D", "mListFragment/onPrepareOptionsMenu() browse_all");
      menu.findItem(android.R.id.home).setEnabled(true).setIcon(R.drawable.ic_home_white_48dp);
      menu.findItem(R.id.browse).setEnabled(false).setIcon(R.drawable.ic_browse_all_black_48dp);
    }
  }

  return super.onPrepareOptionsMenu(menu);
}

If I remove the invalidateOptionsMenu() then my search widget works as expected. When it is there, my search text listener gets called even when I haven't clicked on the search widget at all.

回答1:

I removed...

  SearchView searchView = (SearchView) menu.findItem(R.id.searchactionbaritem).getActionView();     
  searchView.setOnQueryTextListener(queryListener);

from the onCreateOptionsMenu() and put it in the onPrepareOptionsMenu() and it is working normally again.

I hope this helps someone else. I think it has something to do with invalidateOptionsMenu() breaking the SearchView's association with the actionview.



回答2:

Probably, you may be invoking the following code at somewhere in your code :

toolbar.getMenu().clear();

This code removes the listener which you registered for SearchView. Thus, if this is the case, then you should re-register your listener for searchView with the following code :

 searchView.setOnQueryTextListener(queryListener);