Не могу наполнить MatrixCursor

255
05 апреля 2017, 14:09

Добрый вечер!
Есть метод, который делает поисковый запрос на сервер и при помощи ответа наполняет MatrixCursor, который используется для вывода подсказок.
Для обращения к серверу используется библиотека LoopJ AsyncHttpClient

    MatrixCursor searchForSuggestions(String query){  
    MatrixCursor cursor = new MatrixCursor(columns);  
    RequestParams params = new RequestParams();  
    params.add("name", query);  
    get("http://███████████████.tk/api/medicament/search", params, new JsonHttpResponseHandler() {  
        @Override  
        public void onSuccess(int statusCode, Header[] headers, JSONArray response) {  
            if (response.length() > 0) {  
                try {  
                    for (int i = 0; i < 4 && i < response.length(); i++) {  
                        JSONObject object = response.getJSONObject(i);  
                        Object[] values = {i, object.getString("title"), object.getJSONArray("medicaments").getInt(0)};  
                        cursor.addRow(values);  
                        Log.d(TAG, "onSuccess: in the loop");  
                    }  
                } catch (JSONException e) {  
                    e.printStackTrace();  
                }  
            }  
        }  
        @Override  
        public void onFailure(int statusCode, Header[] headers, Throwable throwable, JSONArray errorResponse) {  
            super.onFailure(statusCode, headers, throwable, errorResponse);
        }  
    });  
    Log.d(TAG, "searchForSuggestions: ok");  
    return cursor;  

Проблема в том, что этот метод не ждёт, пока закончится запрос и наполнится курсор, поэтому возвращает его пустым (в LogCat сообщение "searchForSuggestions: ok" появляется раньше, чем "onSuccess: in the loop"). Как следствие, подсказки не отображаются. Как сделать, чтобы onSuccess выполнялся раньше, чем завершается основной метод?

Answer 1

У меня для вас неприятные новости: AsyncHttpClient.get() - это асинхронный запрос, то есть запускается в параллельном потоке, а с недавних пор (с API 19 по-моему) - не асинхронные сетевые вызовы запрещены..., то есть даже если вы вручную начнете лепить синхронный GET - то приложение все равно вывалится с Exception'ом что у вас сетевой вызов в UI треде. Именно по этой причине у вас onSuccess() заканчивается после уже после того как у UI что-то отработает.

Выхода вижу 2:

  1. Обновлять UI элементы уже в onSuccess() правда надо будет предпринять специальные меры, что система не ругалась, что вы обновляете не из UI треда
  2. Кардинально пересмотреть архитектуру приложения, а именно:

    а) вынести все сетевое чтение в Service, которые в фоне наполняют локальную копию удаленной БД

    б) а все запросы, которые вы хотели делать к сети - делать к локальной SQLite

Я бы рекомендовал пойти по 2-му пути - это как бы стандартный и рекомендованный Гуглом паттерн.

READ ALSO
Bottom Navigation View Disabled states

Bottom Navigation View Disabled states

Дано: Bottom Navigation View при выборе элемента background выбранного элемента меняется

223
Перерисовка JPanel

Перерисовка JPanel

Добрый день! Возникла проблема

245
Добавить картинку и еще кое что в Vuforia

Добавить картинку и еще кое что в Vuforia

Всем приветЯ хочу сделать такую прогу: Чтобы при наведении на объект или qr метку, показывала интерфейс с данными об объекте

275