title: Automatic searching as user types
body: <p>I have an Activity where a user types in an EditText, hits a search button, and the app queries a web service and places the results in a ListView.</p>
  
  <p>I'd like to do away with the search button.</p>
  
  <p>Obviously I don't want every character the user types to hit the web service.  I want to only execute 1 web service call when the user is finished typing.</p>
  
  <p>The way I'm achieving this is like so:</p>
  
  <p>I have a member variable which holds an AsyncTask.  When the text in the EditText changes, the AsyncTask fires.  Inside doInBackground(), a call to Thread.sleep() is hit.  This sleep period is essentially a timer waiting to see if the user types anything else.  After the sleep call, the call to the web service is made if the AsyncTask has not been cancelled.  If the user types another letter, cancel() is called on the AsyncTask (to stop the web service from being called), the member variable holding the AsyncTask is set to null, and a new instance of the AsyncTask is created.</p>
  
  <p>I have a few questions here:  Am I leaking memory?  Is this particularly bad in any way?  I understand it may not be most efficient, but am I going to seriously slow down someone's phone?  Is there a better way of doing this?</p>
  
  <pre><code>private SearchTask mSearchTask = null;
  </code></pre>
  
  <p>...</p>
  
  <pre><code>    mSearchText.addTextChangedListener(new TextWatcher() {
  
          public void onTextChanged(CharSequence s, int start, int before, int count) {
              // Auto-generated method stub
          }
  
          public void beforeTextChanged(CharSequence s, int start, int count,
                  int after) {
              // Auto-generated method stub
          }
  
          public void afterTextChanged(Editable s) {
                  if (s != null &amp;&amp; s.length() &gt; 0) {
                      // stop any current search thread
                      if (mSearchTask != null &amp;&amp; !mSearchTask.isCancelled()) {
                          mSearchTask.cancel(false);
                      }
  
  
                          // search for products
                          SearchCriteria crit = new SearchCriteria();
                          crit.strSearchWord = mSearchText.getText().toString().trim();
                          mSearchTask = null;
                          mSearchTask = new SearchTask();
                          mSearchTask.execute(crit);
                  }
          }
      });
  </code></pre>
  
  <p>...</p>
  
  <pre><code>private class SearchTask extends AsyncTask&lt;SearchCriteria, Integer, Boolean&gt; {
      protected Boolean doInBackground(SearchCriteria... params) {
          SearchCriteria crit = null;
          if (params.length &gt; 0) {
              crit = params[0];
  
              if (crit != null) {
                  try {
                      Thread.sleep(1000L);
                      if (!isCancelled()) {
                          // perform search
                          return true;
                      }
                  }
                  catch(Exception e) {
                  }
              }
          }
  
          return false;
      }
  
      protected void onPostExecute(Boolean success) {
          if (success != null &amp;&amp; success == true) {
              // do something
          }
          else {
              // do something else
          }
      }   
  }
  </code></pre>