I have a simple EditText
with a TextChangedListener
and a ListView
.
The onTextChanged
method will call the following restartSearch
method, so the current search thread should be restarted while typing into the EditText
.
The search
method just adds matching items to the ListView
.
When the searchThread
is still alive, I want to cancel and restart the search so the UI doesn't freeze while typing and it doesn't take so long.
Thread searchThread;
private void restartSearch(CharSequence cs){
query = cs;
if(searchThread != null && searchThread.isAlive()){
searchThread.interrupt();
}
searchThread = new Thread(new Runnable() {
public void run() {
if(!lastSearch.equals(query))
search(query);
}
});
searchThread.start();
}
The method from where I call it:
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
EditText etSearch = ((EditText) findViewById(R.id.etSearch));
//...
etSearch.addTextChangedListener(new TextWatcher() {
@Override
public void onTextChanged(CharSequence s, int start, int before, int count) {
// TODO Auto-generated method stub
restartSearch(s);
}
//...
});
}
and another (from where I also update the UI):
final Handler handler = new Handler(){
@Override
public void handleMessage(Message msg) {
if(msg.what==1){
//...
adapter.notifyDataSetChanged();
restartSearch(lastSearch);
}
else if(msg.what==2)
adapter.notifyDataSetChanged();
super.handleMessage(msg);
}
};
the message msg
is sent from the search
method to update the UI:
private void search(CharSequence s){
searchResults.clear();
if(!s.toString().equals("")){
for(int i=0; i<vocsCount; i++){
try{
getResult(i, 0, 2,s);
getResult(i, 1, 1,s);
}catch(Exception ex){}
}
Collections.sort(searchResults);
}
Message msg = handler.obtainMessage();
msg.what = 2;
handler.sendMessage(msg);
lastSearch = s;
}
So as it creates a new Runnable
every time, it seems as if they all run parallel, because all search-items are added multiple times to the ListView.
How can I avoid this?