Intereting Posts
Android: запретить несколько событий onClick на кнопке (которая была отключена) Реагировать на встроенное приложение для Android Как сменить сохранение изображения Ориентация в режиме Portitate в android с использованием Surfaceholder Многострочный TextView в Android? Обратный звонок Android SyncAdapter Внедрение неанглийских символов в Android Sonar: Как использовать градлу для проверки проекта Android Светодиодный фонарик не работает на Samsung Galaxy Nexus Обнаруживать нажатия на кнопки гарнитуры на Android? Преобразование YUV в RGB и отображение с использованием opengl es 2.0 из android ndk с использованием шейдеров Android – сохранение конфиденциальных данных в базе данных sqlite Ограничить длину TextView Самый эффективный способ рисования нескольких одинаковых объектов? Связывание данных – как писать многострочные объявления? Уведомление Android Wear Notification не отображается, если используется FLAG_NO_CLEAR

Android: Как получить поисковые предложения асинхронно из Интернета?

Я создал операцию поиска. Теперь я хочу добавить предложения поиска, которые берутся из веб-службы. Я хочу получить эти предложения асинхронно. В соответствии с добавлением пользовательских предложений мне нужно переопределить метод запроса, выполнить мой поиск предложений, создать собственный MatrixCursor и вернуть его. Но это проблема, мой запрос на получение предложения является асинхронным. Поэтому, когда результат возвращается из сети вне области метода запроса.

Solutions Collecting From Web of "Android: Как получить поисковые предложения асинхронно из Интернета?"

Похоже, что запрос провайдера контента предложения не запускается в потоке пользовательского интерфейса, в любом случае, согласно этому ответу: https://stackoverflow.com/a/12895381/621690 . Если вы можете изменить свой HTTP-запрос, вы можете просто вызвать его блокировку внутри метода запроса. Может помочь прослушивать прерывания или другие сигналы (например, пользовательские), чтобы остановить ненужные запросы.

Другой вариант – если вы не хотите изменять какие-либо классы запросов, которые уже являются асинхронными (например, если вы используете Robospice), нужно просто вернуть ссылку MatrixCursor и заполнить ее позже. Класс AbstractCursor уже реализует шаблон Observer и отправляет уведомления в случае изменений. Если поисковая система прослушивает, она должна обрабатывать любые изменения данных. Мне еще предстоит реализовать это, поэтому я не могу подтвердить, что он будет работать так же хорошо, как я его представляю. (Взгляните на источник CursorLoader для большего вдохновения.)

И, во всяком случае, не все ли курсор? В противном случае мы могли бы просто вернуть список с данными.

UPDATE: для меня использование MatrixCursor не получилось. Вместо этого я реализовал два других решения:

  1. Использование AutoCompleteTextField в сочетании с пользовательским подклассом ArrayAdapter, который сам использует собственный подкласс фильтра. Метод Filter#performFiltering() (который я переопределяю при синхронном вызове удаленной службе) вызывается асинхронно, а поток пользовательского интерфейса не блокируется.
  2. Использование SearchWidget с помощью SearchableActivity и настраиваемого ArrayAdapter (без специального фильтра). Когда начинается поиск, удаленный запрос запускается (Robospice), и когда он возвращается через обратный вызов, я вызываю следующий пользовательский метод в моем ArrayAdapter<Tag> :

     public void addTags(List<Tag> items) { if (items != null && items.size() > 0) { if (Build.VERSION.SDK_INT < Build.VERSION_CODES.HONEYCOMB) { super.setNotifyOnChange(false); for (Tag tag : items) { super.add(tag); } super.notifyDataSetChanged(); } else { super.addAll(items); } } } 

Этот метод позволяет запускать уведомления на адаптере и, следовательно, список результатов поиска.

Вот пример 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; } 

Самое близкое, что я нашел для решения этой проблемы, – это использовать ContentProvider и выполнить сетевой запрос на методе Query вашего провайдера (даже если это противоречит лучшим методам), в результате вы можете создать MatrixCursor поскольку он показан здесь И здесь .

Я по-прежнему ищу другие варианты, такие как использование SyncAdapter , который кажется подавляющим с целью просто показывать предложения, которые больше нигде не используются.

Другой вариант, который я сделал для асинхронного использования, – использовать AutoCompleteTextView, таким образом вы можете создать пользовательский адаптер, где вы можете реализовать функцию getFilter как показано в этом ответе .