Как обращаться с клавишами, нажатыми почти одновременно? - PullRequest
0 голосов
/ 14 февраля 2019

Я пытаюсь решить проблему с панелью поиска.Это работает, но проблема в том, что если я нажму две клавиши почти одновременно, приложение будет искать слова только с нажатой первой клавишей.

Вот журналы:

В этомво-первых, это работает, когда я нажимаю P , а затем R :

[EDT] 0: 4: 9,283 - p

[EDT] 0: 4: 9,348 - 10

[EDT] 0: 4: 9660 - пр

[EDT] 0: 4: 9,722 - 3

Второй нет, потому что я нажимаю P и R почти одновременно:

[EDT] 0: 4: 35,237 - p

[EDT] 0: 4: 35,269 - пр

[EDT] 0: 4: 35,347 - 0

[EDT] 0: 4: 35,347 - 10

Журналы здесь генерируются для показа String поиска и размера результата.Как вы можете видеть, первый случай получает результаты до ввода следующего символа, а второй - все результаты при вводе двух символов.

Основная проблема заключается в том, что во втором случае результаты из 'p'Строка показана вместо тех, что' PR '.

Я использую панель поиска из Toolbar API с addSearchCommand и InfiniteContainer для отображения результатов.

Может ли быть проблема в порядке событий изaddSearchCommand обрабатываются?

РЕДАКТИРОВАТЬ: Вот код на стороне клиента.На стороне сервера это просто простой вызов службы отдыха, который извлекает данные из базы данных.

public static ArrayList<Patient>getSearchedPatient(int index,int amount, String word)
{
    ArrayList<Patient> listPatient = null;
    Response reponse;
    try {
        reponse = RestManager.executeRequest(
            Rest.get(server + "/patients/search")
                .queryParam("index", String.valueOf(index))
                .queryParam("amount", String.valueOf(amount))
                .queryParam("word", word),
            RequestResult.ENTITIES_LIST,
            Patient.class);
        listPatient = (ArrayList<Patient>)reponse.getResponseData();
        Log.p(""+listPatient.size());
    } catch (RestManagerException e) {
        LogError("", e);
    }
    return listPatient; 
}

private static Response executeRequest(RequestBuilder req, RequestResult type, Class objectClass) throws RestManagerException
{

    Response response = null;
    try {
        switch (type) {
        case BYTES:
            response = req.getAsBytes();
            break;
        case JSON_MAP:
            response = req.acceptJson().getAsJsonMap();
            break;
        case ENTITY:
            response = req.acceptJson().getAsProperties(objectClass);
            break;
        case ENTITIES_LIST:
            response = req.acceptJson().getAsPropertyList(objectClass);
            break;
        default:
        case STRING:
            response = req.getAsString();
            break;
        }
    } catch (Exception e) {
        log().error("Erreur à l'exécution de la requête", e);
        response = null;
    }

    if(response == null)
        return null;


    return response;

}

1 Ответ

0 голосов
/ 22 февраля 2019

Итак, хитрость здесь простая.Не отправляйте запрос ... Большинство пользователей набирают текст достаточно быстро, чтобы насытить скорость вашего сетевого подключения, поэтому вы увидите предложения о завершении, относящиеся к вещам, которые больше не актуальны.

Это нетривиальная реализация, которую я подробно обсуждаю в Uber book , где реализована такая функция.

Решение состоит в том, чтобы отправить запрос с задержкой во время кэширования ответов, чтобы избежать двойных запросов и в идеале отменить выполняемый запрос, когда это применимо.Решение в книге Uber делает все 3, я попытаюсь охватить только основы в этом коде макета.Для начала нужно поле для таймера и текущего запроса.В идеале у вас также должна быть карта, содержащая кэшированные данные:

private UITimer delayedRequest;
private String currentSearch;
private Map<String, String> searchCache = new HashMap<>();

Тогда вам нужно привязать слушателя следующим образом:

tb.addSearchCommand(e -> {
    String s = (String)e.getSource();
    if(s == null) {
       if(delayedRequest != null) {
          delayedRequest.cancel();
          delayedRequest = null;
       }
       return;
    }
    if(currentSearch != null && s.equals(currentSearch)) {
       return;
    }
    if(delayedRequest != null) {
       delayedRequest.cancel();
       delayedRequest = null;
    }
    currenSearch = s;
    delayedRequest = UITimer.timer(100, false, () -> {
         doSearchCode();
    });
});

Я не включил здесь использование кэша, которыйВы должны проверить в методе поиска и заполнить код результата.Я также не реализовывал отмену запросов, которые уже выполнялись.

...