I have an EditText
field for which I implemented an TextChangedListener
. In the afterTextChanged
method I call a Volley method which sends the text the user has input to my php script which then queries around 20k records in an online mySQL database for all records which have the user input as a prefix. These are then displayed on screen in a ListView
to the user. This works very well when I type at a reasonable pace or when I view my results to see if what I am looking for has appeared before typing the next letter. However, if I type the whole word without stopping, or type a whole word, delete it and type a new word very fast, which I'm sure some users will do, the search becomes laggy since so many Volley requests are called. I am thinking about how to improve the efficiency of this, so that even when the user types very fast, these problems won't arise. My code is below:
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);
}
}
});
VOLLEY:
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);
}
Even we faced similar kind of issue. What we did was, we put a time period say 1 second or 2 second. So i will call the api whenever there is a time gap of 1 or two seconds between consecutive key events or you can say user takes this much time/pause in typing instead of calling the api everytime something is edited in the edittext.
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
);
}
}
);