ネットワークリソースからクイック検索ボックスに提案を検索します
-
27-09-2019 - |
質問
私はアプリケーションで検索を構築しており、JSON-Arrayとしてサーバーから得られる提案を、クイック検索ボックスの下に表示される提案のリストに掲載する方法が必要です。
クイック検索ボックスにそのようなリソースを読み取らせる簡単な方法はありますか?
現在、私はContentSproviderを使用しようとしていますが、インターフェイスメソッドは、提案を取得するためにデータベースをクエリしていることを明確に示しています。アプリケーション内に保存されているデータを検索している場合、ContentSproviderを使用することは正しい方法だと思います。しかし、ネットワークリソースを照会する必要がある場合、それが正しい方法であることはわかりません。
提案とそのヒット率は時々異なるため、ネットワークから入手する提案をローカルデータベースに保存することは意味がありません。
誰かがこの問題を抱えていましたか?それとも、同様の質問の方向に私を向けることができますか?ここでは、ネットワークの提案に言及したStackで質問を見つけることができませんでした。
解決
developer.android.comでソリューションを見つけました:
ネットワークの場所から入手するという提案がある場合は、サーバーから結果を取得すると、その場でカーソルを構築できます。
これは、ContentSproviderの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;
カーソルは、Quick-Searchボックスで使用されて、提案のリストを記入します。
他のヒント
以下は、ネットワークサービスからの提案を含むSearchViewの例を示します(レトロフィットを使用しました)。
@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の提案に問題がありましたが、それは現れませんでした。検索した後、これの解決策を見つけました。コンテンツプロバイダークラス(Web APIから提案を入手するために)にVolleyを使用しましたが、これはAndroidのコンテンツプロバイダーフレームワークに自然に収まらないようです。また、コンテンツプロバイダーがUIスレッドで実行されることもわかりました。したがって、Volleyの将来を同期して使用した場合、リクエストが返されるまでUIが減速(ブロックされました)(タイムアウト)。さらに、Bolleyの将来のリクエストは、非同期タスクなどの他のスレッドで実行されるべきであるという情報をWebの周りに見つけました。したがって、それは私の問題を解決しませんでした。なぜなら、私がそれを(非同期タスクで)使用する必要がある場合、私は代わりにそもそもVolleyの通常の(非同期)リクエストを使用していたからです(これは私が使用したものでした)。私がしたことはこれでした:
ContentSprovider Subclassでは、リスナーインターフェイスを定義します。
パブリックインターフェイスresultListener {
void onProviderResult(Cursor mCursor); void onProviderError(String errorMsg);
}
私のアクティビティ(LoaderCallbacksを実装した)では、インターフェイスの上にも実装しました。
Singleton Applicationクラスでは、Getter/Setterメソッドとともに、一時的なデータとして使用される静的変数を定義します。
private static hashmap transientData = new Hashmap();
public staticオブジェクトgettransientData(string objectName){
return transientData.get(objectName);
}
public static void settransientData(string objectName、object object){
transientData.put(objectName, object);
}
- 今、論理:アクティビティで、呼び出す前 getsupportloadermanager()。initloader(...), 、 私は呼びました myApplication.settransientData( "requestor"、this) :
私のコンテンツプロバイダーのクラスでは、Bolley RequestのOnResponseコールバックで、これを行いました。
public void onResponse(jsonarray応答){
...
ResultListener requestor = (ResultListener)TheApplication.getTransientData("requestor");
if (requestor!=null) requestor.onProviderResult(mCursor);
}
そのため、Volley Requestが返されると、要求者のコールバックメソッドをトリガーし、応答からのデータで満たされたカーソルを渡し、リクエスター(アクティビティ)に次のように呼び出してカーソルアダプターに通知しました。 adapter.notifydatasetchanged();
これが誰かを助けることを願っています。祝福されます。