1

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?

xoxox
  • 719
  • 1
  • 13
  • 24
  • can you post the search method? – Blackbelt Jun 15 '13 at 15:09
  • you don't need a thread. post your search(query) – Raghunandan Jun 15 '13 at 15:19
  • @Raghunandan I edited my question, I need an extra thread so I can cancel it while the user's typing. – xoxox Jun 16 '13 at 07:57
  • i din't understand you comment. what do you mean by cancel. – Raghunandan Jun 16 '13 at 07:59
  • @Raghunandan For example, when the user types "ab", the method `onTextChanged` will call the `restartSearch` method but the EditText text yet only is "a". To avoid searching for "a", I made a background thread which will be canceled to directly search for "ab", so the current background thread will be killed and recreated. – xoxox Jun 16 '13 at 08:09
  • 1
    you don't need a thread at all. rethink your design. all you need a custom filter to search and update listview – Raghunandan Jun 16 '13 at 08:11
  • 1
    @xoxox check this sample http://stackoverflow.com/questions/10816243/search-in-listview-with-edittext/15367403#15367403. i don't use threads – Raghunandan Jun 16 '13 at 08:21

2 Answers2

0

I don't think you really need to create a thread here. Because GUI is listening on a different thread and when it gives a callback on 'onTextChanged' that happens in a different thread. If these were not two different threads then you would have not been able to keep the GUI responsive while doing the search.

Juned Ahsan
  • 67,789
  • 12
  • 98
  • 136
  • 1
    When I don't do the search in a background thread, the UI won't respond while typing. – xoxox Jun 15 '13 at 17:51
0

You're using Thread.interrupt() but are you querying the value of Thread.interrupted() in your implementation of the thread?

You should check Thread.interrupted() before returning the result from your thread after you've done your search -or even better while you're doing your search if possible-

elmorabea
  • 3,243
  • 1
  • 14
  • 20