Android 将网络资源中的建议搜索到快速搜索框中

Android 将网络资源中的建议搜索到快速搜索框中,android,json,networking,quick-search,Android,Json,Networking,Quick Search,我正在应用程序中构建搜索,需要有一种方法将我从服务器获得的建议(作为JSON数组)放入快速搜索框下方显示的建议列表中 有没有一种简单的方法让快速搜索框读取这些资源 目前我正在尝试使用ContentProvider,但是接口方法清楚地表明应该查询数据库以获得建议。我想如果您搜索存储在应用程序中的数据,使用ContentProvider是正确的方法。但是,如果您需要查询网络资源,我不太确定这是否是正确的方法 对我来说,把从网络上得到的建议保存到本地数据库是没有意义的,因为这些建议和它们的命中率会随着

我正在应用程序中构建搜索,需要有一种方法将我从服务器获得的建议(作为JSON数组)放入快速搜索框下方显示的建议列表中

有没有一种简单的方法让快速搜索框读取这些资源

目前我正在尝试使用ContentProvider,但是接口方法清楚地表明应该查询数据库以获得建议。我想如果您搜索存储在应用程序中的数据,使用ContentProvider是正确的方法。但是,如果您需要查询网络资源,我不太确定这是否是正确的方法

对我来说,把从网络上得到的建议保存到本地数据库是没有意义的,因为这些建议和它们的命中率会随着时间的推移而变化


有人有这个问题吗?或者你能给我指出一个类似问题的方向吗?我在stack上找不到提到网络建议的问题。

在developer.android.com上找到了解决方案:

如果您有从网络位置获得的建议,则可以在从服务器获得结果时动态构建光标

这在ContentProvider的query()方法中:

String[]列={
BaseColumns.\u ID,
SearchManager.SUGGEST\u COLUMN\u TEXT\u 1,
SearchManager.SUGGEST\u列\u意向\u数据
};
MatrixCursor=新的MatrixCursor(列);
对于(int i=0;i

光标在快速搜索框中用于填写建议列表。

以下是一个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
不知道人们是否还需要这个。以防万一,为未来的搜索者。我对SearchView的建议有意见,但没有显示出来。在四处搜寻之后,我找到了解决这个问题的办法。我在我的内容提供者类中使用了截击(从web api中获取建议),这似乎不适合安卓的内容提供者框架。我还发现我的内容提供者确实在UI线程中运行。因此,如果我在其中同步使用Volley的未来,它会减慢(阻止)UI,直到请求返回(超时)。此外,我在网上找到了一些信息,认为Volley未来的请求应该在其他线程中运行,比如在异步任务中,这样它才能正常工作。因此,它并没有解决我的问题,因为如果我必须使用它(在异步任务中),我会首先使用Volley的正常(异步)请求(这就是我当时使用的)。 我所做的是:

  • 在ContentProvider子类中,我定义了一个侦听器接口:

    公共接口结果列表器{

      void onProviderResult(Cursor mCursor);
    
      void onProviderError(String errorMsg);
    
    }

  • 在我的活动(实现了LoaderCallbacks)中,我还实现了上面的接口

  • 在我的单身中
    @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;
    }
    
      void onProviderResult(Cursor mCursor);
    
      void onProviderError(String errorMsg);
    
    return transientData.get(objectName);
    
    transientData.put(objectName, object);
    
      ...
    
      ResultListener requestor =   (ResultListener)TheApplication.getTransientData("requestor");
    
      if (requestor!=null) requestor.onProviderResult(mCursor);