Java — динамический поиск при наборе Android

у меня есть EditText поле для которого я реализовал TextChangedListener, в afterTextChanged метод Я вызываю метод Volley, который отправляет текст, введенный пользователем, в мой php-скрипт, который затем запрашивает около 20 тыс. записей в онлайновой базе данных mySQL для всех записей, в которых пользовательский ввод является префиксом. Затем они отображаются на экране в ListView пользователю. Это работает очень хорошо, когда я печатаю в разумном темпе или когда я просматриваю свои результаты, чтобы увидеть, появилось ли то, что я ищу, перед тем, как печатать следующую букву. Однако, если я набираю все слово без остановки или набираю целое слово, удаляю его и очень быстро набираю новое слово, что, я уверен, что некоторые пользователи сделают, поиск станет запаздывающим, так как вызывается так много запросов Volley. Я думаю о том, как повысить эффективность этого, так что даже когда пользователь набирает очень быстро, эти проблемы не возникнут. Мой код ниже:

TEXTCHANGEDLISTENER:

enter_search.addTextChangedListener(new TextWatcher() {
@Override
public void beforeTextChanged(CharSequence s, int start, int count, int after) {

}

@Override
public void onTextChanged(CharSequence s, int start, int before, int count) {

}

@Override
public void afterTextChanged(Editable s) {
if (enter_search.getText().toString().length() >=2) {
cityresults.clear();
queryCity(enter_search.getText().toString());
}
else {
cityresults.clear();
cityresults.add(new City("Please refine your search.",""));
ArrayAdapter<City> adapter = new EmptyAdapter();
final ListView listView = (ListView) findViewById(R.id.list_view);
listView.setAdapter(adapter);
}
}
});

ВОЛЕЙБОЛ:

public void queryCity(final String query) {

request = new StringRequest(Request.Method.POST, SL_URL, new Response.Listener<String>() {
@Override
public void onResponse(String s) {
try {
cityresults.clear();
JSONArray jsonArray = new JSONArray(s);
for (int i = 0; i < jsonArray.length(); i++) {
JSONObject a = jsonArray.getJSONObject(i);
cityresults.add(new City(a.getString("ascii_name"),(a.getString("timezone"))));
}
if (cityresults.isEmpty()) {
cityresults.add(new City("Please refine your search.",""));
ArrayAdapter<City> adapter = new EmptyAdapter();
final ListView listView = (ListView) findViewById(R.id.list_view);
listView.setAdapter(adapter);
}
else {
ArrayAdapter<City> adapter = new MyListAdapter();
final ListView listView = (ListView) findViewById(R.id.list_view);
listView.setAdapter(adapter);
}}
catch (JSONException e) {
e.printStackTrace();
}
}
}, new Response.ErrorListener() {
@Override
public void onErrorResponse(VolleyError volleyError) {

}
}) {
@Override
protected Map<String, String> getParams() throws AuthFailureError {
HashMap<String, String> hashMap = new HashMap<>();
hashMap.put("search_query", query);
return hashMap;
}
};
queue.add(request);
}

2

Решение

Даже мы столкнулись с подобной проблемой. То, что мы сделали, мы поставили период времени, скажем, 1 секунду или 2 секунды. Поэтому я буду вызывать API всякий раз, когда между последовательными ключевыми событиями будет промежуток времени в 1 или 2 секунды, или вы можете сказать, что пользователь тратит столько времени / пауз в наборе текста вместо вызова API каждый раз, когда что-то редактируется в тексте редактирования.

editText.addTextChangedListener(
new TextWatcher() {
@Override public void onTextChanged(CharSequence s, int start, int before, int count) {}
@Override public void beforeTextChanged(CharSequence s, int start, int count, int after) {}

private Timer timer = new Timer();
private final long DELAY = 500; // milliseconds

@Override
public void afterTextChanged(final Editable s) {
timer.cancel();
timer = new Timer();
timer.schedule(
new TimerTask() {
@Override
public void run() {
// refresh your list
}
},
DELAY
);
}
}
);
4

Другие решения

Других решений пока нет …