【问题标题】:Search suggestions from network resource into Quick Search box从网络资源中搜索建议到快速搜索框中
【发布时间】:2010-11-24 08:04:17
【问题描述】:

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

有没有一种简单的方法可以让快速搜索框读取此类资源?

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

将我从网络获得的建议保存到本地数据库对我来说毫无意义,因为建议及其命中率会不时变化。

有人遇到过这个问题吗?或者可以指出我类似问题的方向吗?我在堆栈上找不到提到网络建议的问题。

【问题讨论】:

  • 看看这里:stackoverflow.com/questions/2123743/… - 我想你可以做什么:一旦用户输入了文本,等待 N 毫秒,然后在文本区域 (...) 下方填充加载视图,开始用于检索结果的异步任务,在异步任务结束时将加载视图替换为结果列表视图。 (根据搜索查询缓存列表视图)。
  • 我想这是一种解决方案,至少在如何显示结果方面是这样。但是,我更多的是寻找一种解决方案,了解如何实现 ContentProvider 并像他们在这里一样添加我的自定义建议:developer.android.com/guide/topics/search/…。只是建议来自网络资源,而不是我的应用程序中的数据。

标签: android json networking quick-search


【解决方案1】:

这是一个 SearchView 示例,其中包含来自网络服务的建议(我使用了 Retrofit):

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

【讨论】:

  • 如果您发布“MyApp.autocompleteService.search”的代码会很棒...
  • 这是一个标准的改造电话
  • 谢谢,工作。我使用 okhttp 代替改造。
  • 简单有效!不需要任何内容​​提供者或无数其他类。谢谢!
  • 这应该是答案。
【解决方案2】:

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

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

这在 ContentProvider 的 query() 方法中:

String[] columns = {
   BaseColumns._ID, 
   SearchManager.SUGGEST_COLUMN_TEXT_1, 
   SearchManager.SUGGEST_COLUMN_INTENT_DATA
};

MatrixCursor cursor = new MatrixCursor(columns);

for (int i = 0; i < arr.length(); i++)
{
  String[] tmp = {Integer.toString(i), arr.getString(i), arr.getString(i)};
  cursor.addRow(tmp);
}
return cursor;

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

【讨论】:

  • 查询中的网络请求在哪里执行?因为它在 UI 线程上,所以我被卡住了。
  • @dbaugh 他已经说过 ... 这在您的 ContentProvider 的 query() 方法中:...
  • 详细解释。我不明白。
【解决方案3】:

不知道人们是否还需要这个。以防万一,为未来的搜索者。我的 SearchView 的建议有问题,但没有显示出来。在四处搜索后,我找到了解决方案。我将 Volley 用于我的内容提供程序类(从 web api 获取建议),这似乎不适合 Android 的内容提供程序框架。我还发现我的内容提供者确实在 UI 线程中运行。因此,如果我在其中同步使用 Volley 的 Future,它会减慢(阻塞)UI,直到请求返回(超时)。此外,我在网上发现了 Volley 的 Future 请求应该在其他线程中运行的信息,例如在 Async 任务中,以使其正常工作。因此,它并没有解决我的问题,因为如果我必须使用它(在异步任务中),我会首先使用 Volley 的正常(异步)请求(这是我当时使用的)。 我所做的是:

  1. 在我的 ContentProvider 子类中,我定义了一个监听器接口:

    公共接口 ResultListener {

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

    }

  2. 在我的活动(实现了 LoaderCallbacks)中,我也实现了上面的接口。

  3. 在我的单例应用程序类中,我定义了一个用作瞬态数据的静态变量,以及它的 getter/setter 方法:

    私有静态HashMap transientData = new HashMap();

    公共静态对象 getTransientData(String objectName) {

    return transientData.get(objectName);
    

    }

    public static void setTransientData(String objectName, Object object) {

    transientData.put(objectName, object);
    

    }

  4. 现在的逻辑: 在activity中,在调用getSupportLoaderManager().initLoader(...)之前, 我调用了 MyApplication.setTransientData("requestor", this)

在我的内容提供者的类中,在凌空请求的 onResponse 回调中,我这样做了:

public void onResponse(JSONArray 响应){

  ...

  ResultListener requestor =   (ResultListener)TheApplication.getTransientData("requestor");

  if (requestor!=null) requestor.onProviderResult(mCursor);

}

这样当 volley 请求返回时,它会触发请求者的回调方法,将响应中填充了数据的游标传递给它,然后请求者(活动)通过调用通知游标适配器: 适配器.swapCursor(c); 适配器.notifyDataSetChanged();

希望这对某人有所帮助。 祝福。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-05-11
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多