【发布时间】:2016-08-20 18:51:45
【问题描述】:
我在我的应用程序中实现了一个 Searchview,但遇到了一个奇怪的问题。基本上,用户可以输入要搜索的字符串并正确提交。但是,我的应用程序将根据搜索查询过滤 ListView,然后将启动一个 Intent,导致 Activity 再次启动并返回到显示所有结果的原始状态。
这是相关代码。
@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);
}
我无法改变这种行为,也找不到任何关于它在线实施的文档。有没有办法可以覆盖此功能并阻止它启动意图并将 Activity 重新启动到其原始未过滤状态?
编辑:
我能够自己解决这个问题。对于任何可能遇到同样问题的人,我的解决方案是。
所以我在我的 AndroidManifest.xml 中有一个意图过滤器,位于将在搜索操作时启动意图的活动下。这就是导致它启动意图并启动我的活动的新实例的原因。
我对此的解决方案是将此活动转换为单个顶级活动并添加代码来处理意图。通过使 Activity 成为单一顶部,它允许 Activity 处理传入的 Intent,而无需启动 Intent 的新实例。关于普通和单顶活动的区别的更详细的描述,这是一篇关于主题的好文章https://www.mobomo.com/2011/06/android-understanding-activity-launchmode/
现在,因为我的活动是单顶活动,所以我可以覆盖 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>
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);
}
}
我希望这会有所帮助。
【问题讨论】:
-
只是为了测试你能不能从
onQueryTextChange()返回false。你的问题其实很奇怪。理想情况下,从onQueryTextSubmit()返回true应该不会导致这个问题,因为你告诉系统你已经处理了查询提交,并且不应该有任何意图启动。 developer.android.com/reference/android/widget/… -
如何测试是否可以从 onQueryTextChange() 返回 false?据我所知,我能够做到,因为它当前返回 false 并且没有导致任何错误。
标签: java android android-intent