Android:如何从web异步获取搜索建议?
我已经创建了一个可搜索的活动。现在,我想添加来自web服务的搜索建议。我希望异步获取这些建议。根据需要,我需要覆盖查询方法,执行我的建议搜索,构建我自己的并返回它。但这就是问题所在,我获取建议的请求是异步的。所以,当结果从网络返回时,它将超出查询方法的范围 我发现最接近解决这个问题的方法是使用ContentProvider,并使用提供商的Android:如何从web异步获取搜索建议?,android,search,search-suggestion,Android,Search,Search Suggestion,我已经创建了一个可搜索的活动。现在,我想添加来自web服务的搜索建议。我希望异步获取这些建议。根据需要,我需要覆盖查询方法,执行我的建议搜索,构建我自己的并返回它。但这就是问题所在,我获取建议的请求是异步的。所以,当结果从网络返回时,它将超出查询方法的范围 我发现最接近解决这个问题的方法是使用ContentProvider,并使用提供商的Query方法执行网络请求(即使这违反了最佳实践),结果是您可以创建一个MatrixCursor,如图所示 我还在搜索其他选项,比如使用SyncAdapter,
Query
方法执行网络请求(即使这违反了最佳实践),结果是您可以创建一个MatrixCursor
,如图所示
我还在搜索其他选项,比如使用SyncAdapter
,这似乎是为了显示其他地方没有使用过的建议
我异步执行此操作的另一个选项是使用AutoCompleteTextView,这样您可以创建一个自定义适配器,在其中可以实现
getFilter
函数,如中所示。根据以下回答,对建议内容提供程序的请求似乎没有在UI线程上运行:。
如果可以更改http请求,只需在查询方法内部将其称为阻塞。可能有助于侦听中断或其他信号(可能是自定义信号),以停止不必要的请求
另一种选择——如果您不想更改任何已经是异步的请求类(如您正在使用Robospice)——应该只是返回MatrixCursor引用,然后填充它。AbstractCursor类已经实现了Observer模式,并在发生更改时发送通知。如果搜索系统正在侦听,它应该处理数据中的任何更改。我自己还没有实现,所以我不能确认它是否会像我想象的那样好。(更多灵感,请查看CursorLoader的来源。)
不管怎样,这不是光标的全部点吗?否则,我们可以简单地返回一个包含数据的列表
更新:
对我来说,使用MatrixCursor是行不通的。相反,我实施了另外两种解决方案:
Filter#performFiltering()
(我通过对远程服务的同步调用覆盖该方法),并且UI线程不会被阻塞ArrayAdapter
子类上调用以下自定义方法:
public void addTags(List<Tag> items) {
if (items != null && items.size() > 0) {
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.HONEYCOMB) {
super.setNotifyOnChange(false);
for (Tag tag : items) {
super.add(tag);
}
super.notifyDataSetChanged();
} else {
super.addAll(items);
}
}
}
public void addTags(列表项){
if(items!=null&&items.size()>0){
if(Build.VERSION.SDK\u INT
此方法负责触发适配器上的通知,从而触发搜索结果列表。下面是一个SearchView示例,其中包含来自网络服务的建议(我使用了改型):
@覆盖
公共布尔onCreateOptions菜单(菜单){
//为菜单充气;这会将项目添加到操作栏(如果存在)。
getMenuInflater().充气(R.menu.menu\u搜索活动,菜单);
final SearchView SearchView=(SearchView)MenuItemCompat.getActionView(menu.findItem(R.id.search));
final CursorAdapter suggestionAdapter=新的SimpleCursorAdapter(此,
android.R.layout.simple\u list\u item\u 1,
无效的
新字符串[]{SearchManager.SUGGEST_COLUMN_TEXT_1},
新int[]{android.R.id.text1},
0);
最终列表建议=新建ArrayList();
searchView.setSuggestionAdapter(suggestionAdapter);
searchView.setOnSuggestionListener(新的searchView.OnSuggestionListener(){
@凌驾
公共布尔值onSuggestionSelect(整数位置){
返回false;
}
@凌驾
公共布尔onSuggestionClick(整数位置){
searchView.setQuery(建议.get(位置),false);
searchView.clearFocus();
doSearch(建议.获取(位置));
返回true;
}
});
searchView.setOnQueryTextListener(新的searchView.OnQueryTextListener(){
@凌驾
公共布尔值onQueryTextSubmit(字符串查询){
返回false;
}
@凌驾
公共布尔onQueryTextChange(字符串newText){
MyApp.autocompleteService.search(newText,newcallback()){
@凌驾
public void成功(自动完成、自动完成、响应){
建议。清晰();
建议.addAll(自动完成.建议);
字符串[]列={
BaseColumns.\u ID,
SearchManager.SUGGEST\u COLUMN\u TEXT\u 1,
SearchManager.SUGGEST\u列\u意向\u数据
};
MatrixCursor=新的MatrixCursor(列);
对于(int i=0;i@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_search_activity, menu);
final SearchView searchView = (SearchView) MenuItemCompat.getActionView(menu.findItem(R.id.search));
final CursorAdapter suggestionAdapter = new SimpleCursorAdapter(this,
android.R.layout.simple_list_item_1,
null,
new String[]{SearchManager.SUGGEST_COLUMN_TEXT_1},
new int[]{android.R.id.text1},
0);
final List<String> suggestions = new ArrayList<>();
searchView.setSuggestionsAdapter(suggestionAdapter);
searchView.setOnSuggestionListener(new SearchView.OnSuggestionListener() {
@Override
public boolean onSuggestionSelect(int position) {
return false;
}
@Override
public boolean onSuggestionClick(int position) {
searchView.setQuery(suggestions.get(position), false);
searchView.clearFocus();
doSearch(suggestions.get(position));
return true;
}
});
searchView.setOnQueryTextListener(new SearchView.OnQueryTextListener() {
@Override
public boolean onQueryTextSubmit(String query) {
return false;
}
@Override
public boolean onQueryTextChange(String newText) {
MyApp.autocompleteService.search(newText, new Callback<Autocomplete>() {
@Override
public void success(Autocomplete autocomplete, Response response) {
suggestions.clear();
suggestions.addAll(autocomplete.suggestions);
String[] columns = {
BaseColumns._ID,
SearchManager.SUGGEST_COLUMN_TEXT_1,
SearchManager.SUGGEST_COLUMN_INTENT_DATA
};
MatrixCursor cursor = new MatrixCursor(columns);
for (int i = 0; i < autocomplete.suggestions.size(); i++) {
String[] tmp = {Integer.toString(i), autocomplete.suggestions.get(i), autocomplete.suggestions.get(i)};
cursor.addRow(tmp);
}
suggestionAdapter.swapCursor(cursor);
}
@Override
public void failure(RetrofitError error) {
Toast.makeText(SearchFoodActivity.this, error.getMessage(), Toast.LENGTH_SHORT).show();
Log.w("autocompleteService", error.getMessage());
}
});
return false;
}
});
return true;
}