1

I have implemented a Searchview into my application, and have run into a weird problem. Basically, the user is able to enter a string to be searched and it is submitted properly. However, my application will filter the ListView based on the search query, and then an Intent will be launched resulting in the activity starting again and returning to it's original state where it is displaying all the results.

Here is the related code.

@Override
public boolean onCreateOptionsMenu(Menu menu) {
    ...
    searchView.setOnQueryTextListener(new SearchView.OnQueryTextListener() {
        @Override
        public boolean onQueryTextSubmit(String query) {
            updateEntriesView(dbHelper.queryByName(query));
            Toast.makeText(getApplicationContext(), "Searching for " + query, Toast.LENGTH_LONG).show();
            return true;
        }

        @Override
        public boolean onQueryTextChange(String newText) {
            return false;
        }
    });
}

private void updateEntriesView(ArrayList<Entry> response) {
    mListView = (ListView) findViewById(R.id.listview_entries);
    if (adapter == null) {
        adapter = new EntryListAdapter(EntriesActivity.this, R.layout.row_entry_layout, response);
        mListView.setAdapter(adapter);
    } else {
        adapter.clear();
        adapter.addAll(response);
        adapter.notifyDataSetChanged();
    }
    adapter.setNotifyOnChange(true);
}

I can not figure out to change this behavior and I can not find any documentation regarding it's implementation online. Is there a way I can override this feature and prevent it from launching an intent and restarting the activity to it's original unfiltered state?

EDIT:
I was able to solve this issue myself. For anyone who may be having the same problem here was my solution.

So I had an intent-filter in my AndroidManifest.xml under the activity that would launch an intent upon a search action. This is what was causing it to launch an intent and start a new instance of my activity.

My solution to this was to convert this activity into a single top activity and add code to handle the intent. By making the activity single top, it allows the activity to handle incoming intents without starting up a new instance of the intent. For a more detailed description on the difference between a normal and single top activity, this is a good article on the subject https://www.mobomo.com/2011/06/android-understanding-activity-launchmode/

Now, because my activity is single top, I can override the onNewIntent() method and add my code for handling this intent without having it launch a new instance. The relevant code for solving my problem is below.

AndroidManifest.xml

<activity android:name=".EntriesActivity"
    android:launchMode="singleTop">
    <intent-filter>
        <action android:name="android.intent.action.SEARCH" />
    </intent-filter>
    <meta-data
        android:name="android.app.searchable"
        android:resource="@xml/searchable"></meta-data>
</activity>

EntriesActivity.java

public class EntriesActivity extends AppCompatActivity {
    ...
    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        ...
        searchView.setOnQueryTextListener(new SearchView.OnQueryTextListener() {
            @Override
            public boolean onQueryTextSubmit(String query) {
                updateEntriesView(dbHelper.queryByName(query));
                Toast.makeText(getApplicationContext(), "Searching for " + query, Toast.LENGTH_LONG).show();
                return true;
            }

            @Override
            public boolean onQueryTextChange(String newText) {
                return false;
            }
        });
    }

    @Override
    protected void onNewIntent(Intent intent) {
        super.onNewIntent(intent);
        handleIntent(intent);
    }

    private void handleIntent(Intent intent) {
        if (Intent.ACTION_SEARCH.equals(intent.getAction())) {
            String query = intent.getStringExtra(SearchManager.QUERY);
            updateEntriesView(dbHelper.queryEntriesByName(query));
        }
    }

    private void updateEntriesView(ArrayList<Entry> response) {
        if (adapter == null) {
             adapter = new EntryListAdapter(EntriesActivity.this, R.layout.row_entry_layout, response);
            mEntriesList.setAdapter(adapter);
        } else {
            adapter.clear();
            adapter.addAll(response);
            adapter.notifyDataSetChanged();
        }
        adapter.setNotifyOnChange(true);
    }
}

I hope this helps.

aestamper
  • 141
  • 1
  • 8
  • Just to test can you return false from `onQueryTextChange()`. Your problem is in fact really strange. Ideally returning `true` from `onQueryTextSubmit()` should not cause this issue, because then you are telling the system that you have handled the query submit, and there should not be any intent launched. http://developer.android.com/reference/android/widget/SearchView.OnQueryTextListener.html#onQueryTextSubmit(java.lang.String) – Antrromet Apr 26 '16 at 19:08
  • How can I test if I can return false from onQueryTextChange()? As far as I can tell I am able to, since it is currently returning false and is not causing any errors. – aestamper Apr 26 '16 at 19:15

2 Answers2

0

You need to clear focus of the text view using searchView.clearFocus(); Refer This Answer: https://stackoverflow.com/a/15127252/7710739

Reejesh PK
  • 658
  • 1
  • 11
  • 27
0

I know this is old but if your searching and resulting in the same Activity try removing the

    <intent-filter>
    <action android:name="android.intent.action.SEARCH" />
    </intent-filter>

It should not try to launch a new activity then i don't beleive.

Mark Vance
  • 166
  • 9