Java Android SearchView.OnQueryTextListener()意外启动了一个Intent

Java Android SearchView.OnQueryTextListener()意外启动了一个Intent,java,android,android-intent,Java,Android,Android Intent,我在我的应用程序中实现了一个Searchview,但遇到了一个奇怪的问题。基本上,用户可以输入要搜索的字符串并正确提交。但是,我的应用程序将根据搜索查询过滤ListView,然后启动一个意图,导致活动再次启动,并返回到显示所有结果的原始状态 这是相关代码 @Override public boolean onCreateOptionsMenu(Menu menu) { ... searchView.setOnQueryTextListener(new SearchView.OnQ

我在我的应用程序中实现了一个Searchview,但遇到了一个奇怪的问题。基本上,用户可以输入要搜索的字符串并正确提交。但是,我的应用程序将根据搜索查询过滤ListView,然后启动一个意图,导致活动再次启动,并返回到显示所有结果的原始状态

这是相关代码

@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);
}
@覆盖
公共布尔onCreateOptions菜单(菜单){
...
searchView.setOnQueryTextListener(新的searchView.OnQueryTextListener(){
@凌驾
公共布尔值onQueryTextSubmit(字符串查询){
updateEntriesView(dbHelper.queryByName(查询));
Toast.makeText(getApplicationContext(),“搜索”+查询,Toast.LENGTH\u LONG.show();
返回true;
}
@凌驾
公共布尔onQueryTextChange(字符串newText){
返回false;
}
});
}
私有void updateEntriesView(ArrayList响应){
mListView=(ListView)findViewById(R.id.ListView_条目);
if(适配器==null){
适配器=新的EntryListAdapter(EntriesActivity.this,R.layout.row\u entry\u layout,response);
mListView.setAdapter(适配器);
}否则{
适配器。清除();
adapter.addAll(响应);
adapter.notifyDataSetChanged();
}
adapter.setNotifyOnChange(true);
}
我不知道如何改变这种行为,也找不到任何关于它的在线实现的文档。是否有方法可以覆盖此功能并阻止它启动意图并将活动重新启动到其原始未筛选状态

编辑:
我自己能够解决这个问题。对于任何可能有同样问题的人,我的解决方案就是这样

因此,我在我的AndroidManifest.xml中的活动下有一个意图过滤器,它将在搜索操作时启动意图。这就是导致它启动意图并启动我的活动的新实例的原因

我的解决方案是将此活动转换为单个顶级活动,并添加代码来处理意图。通过使活动成为单顶部,它允许活动处理传入的意图,而无需启动意图的新实例。要更详细地描述正常活动和单个顶级活动之间的区别,这是一篇关于此主题的好文章

现在,因为我的活动是单顶的,所以我可以重写onNewIntent()方法并添加代码来处理此意图,而无需让它启动新实例。下面是解决我的问题的相关代码

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>
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);
    }
}

EntriesActivity.java

<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>
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);
    }
}
公共类EntriesActivity扩展了AppCompatActivity{
...
@凌驾
公共布尔onCreateOptions菜单(菜单){
...
searchView.setOnQueryTextListener(新的searchView.OnQueryTextListener(){
@凌驾
公共布尔值onQueryTextSubmit(字符串查询){
updateEntriesView(dbHelper.queryByName(查询));
Toast.makeText(getApplicationContext(),“搜索”+查询,Toast.LENGTH\u LONG.show();
返回true;
}
@凌驾
公共布尔onQueryTextChange(字符串newText){
返回false;
}
});
}
@凌驾
受保护的void onNewIntent(意图){
super.onNewIntent(意向);
手册内容(意图);
}
私人无效手册内容(意图){
if(Intent.ACTION_SEARCH.equals(Intent.getAction())){
String query=intent.getStringExtra(SearchManager.query);
updateEntriesView(dbHelper.queryEntriesByName(查询));
}
}
私有void updateEntriesView(ArrayList响应){
if(适配器==null){
适配器=新的EntryListAdapter(EntriesActivity.this,R.layout.row\u entry\u layout,response);
mEntriesList.setAdapter(适配器);
}否则{
适配器。清除();
adapter.addAll(响应);
adapter.notifyDataSetChanged();
}
adapter.setNotifyOnChange(true);
}
}

我希望这会有所帮助。

您需要使用
searchView.clearFocus()清除文本视图的焦点

参考此答案:

您需要使用
searchView.clearFocus()清除文本视图的焦点

请参考此答案:

我知道这是旧的,但如果您的搜索结果是相同的活动,请尝试删除

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


它不应该尝试启动一个新的活动,那么我不相信。

我知道这是旧的,但是如果您搜索并导致相同的活动,请尝试删除

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


它不应该尝试启动一个新的活动,那么我就不相信了。

为了测试,您可以从
onQueryTextChange()
返回false。你的问题其实很奇怪。理想情况下,从
onquerytexsubmit()
返回
true
不会导致此问题,因为这样您就告诉系统您已经处理了查询提交,并且不应该启动任何意图。如何测试onQueryTextChange()是否返回false?据我所知,我可以这样做,因为它当前返回false并且没有导致任何错误。为了测试,您可以从
onquerytexchange()
返回false。你的问题其实很奇怪。理想情况下,从
onquerytexsubmit()
返回
true
不会导致此问题,因为这样您就告诉系统您已经处理了查询提交,并且不应该启动任何意图。如何测试onQueryTextChange()是否返回false?据我所知,我能做到,因为现在是晚上