android - resultados - Busque sugerencias de recursos de red en el cuadro de búsqueda rápida
porque no puedo buscar en google desde mi celular (3)
Estoy construyendo la búsqueda en una aplicación y necesito tener una forma de poner las sugerencias que recibo de mi servidor como una matriz JSON en la lista de sugerencias que se muestra debajo del Cuadro de búsqueda rápida.
¿Existe una manera fácil de hacer que el cuadro de búsqueda rápida lea dichos recursos?
Actualmente estoy intentando usar un ContentProvider, pero los métodos de la interfaz indican claramente que se supone que uno debe consultar una base de datos para obtener las sugerencias. Supongo que usar un ContentProvider es la forma correcta si está buscando los datos que están almacenados dentro de la aplicación. Sin embargo, no estoy tan seguro de que sea la manera correcta si necesita consultar un recurso de red.
No tiene sentido para mí guardar las sugerencias que recibo de la red en una base de datos local, ya que las sugerencias y su tasa de aciertos variarán de vez en cuando.
Alguien ha tenido este problema? ¿O me puede indicar la dirección de una pregunta similar? No pude encontrar preguntas aquí en la pila que mencionan sugerencias de red.
Encontró la solución en developer.android.com:
Si tiene sugerencias que recibe de una ubicación de red, puede construir un cursor sobre la marcha cuando obtenga los resultados de su servidor.
Esto va dentro del método de consulta () de su 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;
El cursor es el que se usa en el cuadro de búsqueda rápida para completar una lista de sugerencias.
Este es un ejemplo de SearchView con sugerencias provenientes de un servicio de red (usé 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;
}
No sé si la gente todavía necesita esto. Por si acaso, para futuros buscadores. Tuve un problema con las sugerencias de mi SearchView, que no aparecieron. Después de buscar alrededor, encontré una solución para esto. Utilicé Volley para mi clase de proveedor de contenido (para obtener las sugerencias de la API web), que parecía no encajar naturalmente en el marco del proveedor de contenido de Android. También encontré que mi proveedor de contenido se ejecuta en el hilo de la interfaz de usuario. Por lo tanto, si usé el Volley''s Future en forma síncrona, ralentizó (bloqueó) la interfaz de usuario hasta que se devolvió la solicitud (tiempo de espera). Además, encontré información en la web que la solicitud de Volley''s Future debería ejecutarse en otro hilo, como en una tarea Async, para que funcione bien. Por lo tanto, no resolvió mi problema, porque si tuviera que usarlo (en una tarea asíncrona), habría utilizado la solicitud normal (asíncrona) de Volley en primer lugar (que era lo que usé entonces). Lo que hice fue esto:
En mi subclase ContentProvider, defino una interfaz de escucha:
interfaz pública ResultListener {
void onProviderResult(Cursor mCursor); void onProviderError(String errorMsg);
}
En mi actividad (que implementó LoaderCallbacks), implementé también la interfaz anterior.
En mi clase de aplicación Singleton, defino una variable estática que se usa como datos transitorios, junto con sus métodos de obtención / establecimiento:
HashMap estático privado transientData = new HashMap ();
Objeto estático público getTransientData (String objectName) {
return transientData.get(objectName);
}
public static void setTransientData (String objectName, Object object) {
transientData.put(objectName, object);
}
- ahora la lógica: en la actividad, antes de llamar a getSupportLoaderManager (). initLoader (...) , llamé a MyApplication.setTransientData ("requestor", this) :
En la clase de mi proveedor de contenido, en la devolución de llamada onResponse de la solicitud de volea, hice esto:
public void onResponse (respuesta JSONArray) {
...
ResultListener requestor = (ResultListener)TheApplication.getTransientData("requestor");
if (requestor!=null) requestor.onProviderResult(mCursor);
}
De modo que cuando se devuelva la solicitud de volea, activará el método de devolución de llamada del solicitante, pasándole el cursor lleno de datos de la respuesta y, a su vez, el solicitante (la actividad) notificó al adaptador del cursor llamando a: adapter.swapCursor (c); adapter.notifyDataSetChanged ();
Espero que esto ayude a alguien. Se bendecido.