将网络资源中的搜索建议放入快速搜索框中
-
27-09-2019 - |
题
我正在应用程序中构建搜索,并且需要有一种方法将从我的服务器以 JSON 数组形式获得的建议放入快速搜索框下方显示的建议列表中。
有没有简单的方法让快速搜索框读取此类资源?
目前我正在尝试使用 ContentProvider,但接口方法清楚地表明应该查询数据库来获取建议。我想如果您正在搜索存储在应用程序内部的数据,那么使用 ContentProvider 是正确的方法。但是,我不太确定如果您需要查询网络资源,这是否是正确的方法。
对我来说,将从网络获得的建议保存到本地数据库是没有意义的,因为建议及其命中率会不时变化。
有人遇到过这个问题吗?或者可以为我指出类似问题的方向吗?我在堆栈上找不到提到网络建议的问题。
解决方案
实测值上developer.android.com溶液:
如果您有任何建议您从网络位置得到,你可以在飞行中建立一个光标,当您从服务器得到的结果。
此去您的ContentProvider的查询()方法中:
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;
光标中快速搜索框用于填充的建议列表。
其他提示
下面是搜索查看与建议从网络服务(我使用改造)未来的示例:
@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;
}
不知道人们是否还需要这个。以防万一,供未来的搜索者使用。我的 SearchView 的建议有问题,但没有显示。经过一番搜索,我找到了解决这个问题的方法。我将 Volley 用于我的内容提供程序类(从 Web api 获取建议),它似乎并不自然地适合 Android 的内容提供程序框架。我还发现我的内容提供程序确实在 UI 线程中运行。因此,如果我在其中同步使用 Volley 的 Future,它会减慢(阻塞)UI,直到请求返回(超时)。另外,我在网上发现了一些信息,Volley 的 Future 请求应该在其他线程中运行,例如在异步任务中,才能正常工作。因此,它并没有解决我的问题,因为如果我必须使用它(在异步任务中),我会首先使用 Volley 的正常(异步)请求(这就是我当时使用的)。我所做的是这样的:
在我的 ContentProvider 子类中,我定义了一个侦听器接口:
公共接口结果监听器{
void onProviderResult(Cursor mCursor); void onProviderError(String errorMsg);
}
在我的活动(实现了 LoaderCallbacks)中,我还实现了上面的接口。
在我的单例应用程序类中,我定义了一个用作瞬态数据的静态变量及其 getter/setter 方法:
私有静态 HashMap 瞬态数据 = new HashMap();
公共静态对象 getTransientData(String objectName) {
return transientData.get(objectName);
}
公共静态无效setTransientData(字符串对象名,对象对象){
transientData.put(objectName, object);
}
- 现在的逻辑:在活动中,调用之前 getSupportLoaderManager().initLoader(...), 我打电话 MyApplication.setTransientData("请求者", this) :
在我的内容提供者的类中,在齐射请求的 onResponse 回调中,我这样做了:
公共无效onResponse(JSONArray响应){
...
ResultListener requestor = (ResultListener)TheApplication.getTransientData("requestor");
if (requestor!=null) requestor.onProviderResult(mCursor);
}
这样,当 volley 请求返回时,它将触发请求者的回调方法,将填充有响应数据的游标传递给它,然后请求者(活动)通过调用以下方式通知游标适配器:适配器.swapCursor(c);适配器.notifyDataSetChanged();
希望这对某人有帮助。祝福。