androidandroid-viewmodelandroid-textwatcher

How to get ViewModel observer to not observe initially?


I have a SearchView icon on the Toolbar via onCreateOptionsMenu(Menu menu). A click on the icon creates an EditText line for the user to enter search inputs. I have a TextWatcher() attached to the EditText line so that when text is added to the line (afterTextChanged Editable s) a searchQuery method is run via the ViewModel that searches a Room database.

My problem is that the observer is firing upon creation even before the user enters any query. Using Toasts, I was able to confirm that the observer is running a blank query "%%" right when the SearchView icon is pressed by the user and before the user enters any search query. And this is happening even though the observer is set up in the afterTextChanged(). How do I get the ViewModel observer to only fire after text is entered by the user?

Activity
...
@Override
public boolean onCreateOptionsMenu(Menu menu) {

getMenuInflater().inflate(R.menu.mainactiv_menu, menu);
searchItem = menu.findItem(R.id.action_search);
menu.findItem(R.id.action_search).setVisible(false);
if (cardsAdapter != null && cardsAdapter.getItemCount() > 0) {
    menu.findItem(R.id.action_search).setVisible(true);
}
SearchManager searchManager = (SearchManager) MainActivity.this.getSystemService(Context.SEARCH_SERVICE);
if (searchItem != null) {
    mSearchView = (SearchView) searchItem.getActionView();
    if (mSearchView != null) {
        mSearchView.setSearchableInfo(searchManager.getSearchableInfo(getComponentName()));
        EditText mSearchEditText = mSearchView.findViewById(androidx.appcompat.R.id.search_src_text);
        mSearchEditText.setInputType(android.text.InputType.TYPE_TEXT_FLAG_NO_SUGGESTIONS);
        mSearchEditText.addTextChangedListener(new TextWatcher() {

            @Override
            public void beforeTextChanged(CharSequence s, int start, int count, int after) {
               // not needed
            }

            @Override
            public void onTextChanged(CharSequence s, int start, int before, int count) {
                // not needed
            }

            @Override
            public void afterTextChanged(Editable s) {

                String queryText = "%" + s.toString() + "%";

                mQuickcardViewModel.searchQuery(queryText).observe(MainActivity.this, searchCards -> {

                    searchList = searchCards;

                    if (!mSearchView.isIconified() && searchList.size() > 0) {
                        // do something
                    } 

                    ...     

Solution

  • How do I get the ViewModel observer to only fire after text is entered by the user?

    Use an if statement to see if the string is empty before observing:

    @Override
    public void afterTextChanged(Editable s) {
         if (s.toString().length() > 0) {
             // the rest of your code goes here, preferably with some modifications
         }
    }
    

    Other changes that I would recommend include: