17

私はアプリケーションで検索を構築しており、サーバーから取得した提案をJSON配列として、クイック検索ボックスの下に表示される提案のリストに配置する方法が必要です。

クイック検索ボックスにそのようなリソースを読み取らせる簡単な方法はありますか?

現在、ContentProviderを使用しようとしていますが、インターフェイスメソッドは、提案を取得するためにデータベースにクエリを実行することになっていることを明確に示しています。アプリケーション内に保存されているデータを検索する場合は、ContentProviderを使用するのが正しい方法だと思います。ただし、ネットワークリソースを照会する必要がある場合に、それが正しい方法であるかどうかはわかりません。

提案とそのヒット率は時々変化するため、ネットワークから取得した提案をローカルデータベースに保存することは意味がありません。

誰かがこの問題を抱えていましたか?または、同様の質問の方向に私を向けることができますか?ここで、ネットワークの提案に言及している質問をスタックで見つけることができませんでした。

4

3 に答える 3

13

これは、ネットワークサービス(私はRetrofitを使用しました)からの提案を含む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;
}
于 2015-05-04T14:17:06.070 に答える
12

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;

カーソルは、クイック検索ボックスで候補のリストを入力するために使用されます。

于 2010-11-24T12:50:51.943 に答える
0

人々がまだこれを必要としているかどうかわからない。念のため、将来の検索者のために。SearchViewの提案に問題がありましたが、表示されませんでした。周りを検索した後、私はこれに対する解決策を見つけました。私はコンテンツプロバイダークラスにVolleyを使用しました(Web APIからの提案を取得するため)。これは、Androidのコンテンツプロバイダーフレームワークに自然に適合しないようでした。また、コンテンツプロバイダーがUIスレッドで実行されていることもわかりました。したがって、Volley's Futureを同期的に使用すると、リクエストが返される(タイムアウト)までUIの速度が低下(ブロック)されました。さらに、VolleyのFutureリクエストを正常に機能させるには、非同期タスクなどの他のスレッドで実行する必要があるという情報をWebで見つけました。したがって、(非同期タスクで)使用する必要がある場合は、Volleyを使用していたため、問題は解決しませんでした。代わりに、そもそも通常の(非同期)リクエスト(それは私が当時使用していたものでした)。私がしたことはこれでした:

  1. ContentProviderサブクラスで、リスナーインターフェイスを定義します。

    パブリックインターフェイスResultListener{

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

    }

  2. 私のアクティビティ(LoaderCallbacksを実装)では、上記のインターフェイスも実装しました。

  3. 私のシングルトンアプリケーションクラスでは、一時データとして使用される静的変数を、そのゲッター/セッターメソッドとともに定義します。

    private static HashMaptransientData = new HashMap();

    public static Object getTransientData(String objectName){

    return transientData.get(objectName);
    

    }

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

    transientData.put(objectName, object);
    

    }

  4. ロジック:アクティビティで、getSupportLoaderManager()。initLoader(...)を呼び出す前に、 MyApplication.setTransientData( "requestor"、this)を呼び出しました。

私のコンテンツプロバイダーのクラスでは、ボレーリクエストのonResponseコールバックで、次のようにしました。

public void onResponse(JSONArray response){

  ...

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

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

}

ボレーリクエストが返されると、リクエスターのコールバックメソッドがトリガーされ、レスポンスからのデータで満たされたカーソルが渡されます。次に、リクエスター(アクティビティ)は、次の呼び出しによってカーソルアダプターに通知します。adapter.swapCursor(c); adapter.notifyDataSetChanged();

これが誰かを助けることを願っています。祝福されます。

于 2016-04-30T19:52:02.987 に答える