Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Automatic searching as user types

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.

I'd like to do away with the search button.

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.

The way I'm achieving this is like so:

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.

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?

private SearchTask mSearchTask = null;

...

    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 && s.length() > 0) {
                    // stop any current search thread
                    if (mSearchTask != null && !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);
                }
        }
    });

...

private class SearchTask extends AsyncTask<SearchCriteria, Integer, Boolean> {
    protected Boolean doInBackground(SearchCriteria... params) {
        SearchCriteria crit = null;
        if (params.length > 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 && success == true) {
            // do something
        }
        else {
            // do something else
        }
    }   
}
like image 835
Andrew Avatar asked May 18 '11 15:05

Andrew


People also ask

What is search as you type called?

This feature, or variations thereof, has also been referred to as Autocomplete, search as you type, filter/find as you type (FAYT), incremental search, typeahead search, inline search, instant search, word wheeling, and other names as well.

What is auto suggestion in search?

Autocomplete is a feature within Google Search that makes it faster to complete searches that you start to type. Our automated systems generate predictions that help people save time by allowing them to quickly complete the search they already intended to do.

What is predictive searching?

Predictive search is an online search approach that aims at anticipating the search needs of a user, by making suggestions related to their queries as they type in a search bar. The final goal is to save time for the user by letting them click on the suggestions instead of forcing them to complete their queries.


3 Answers

I would be more tempted to launch a thread in x milliseconds and do the check then, as opposed to launching the thread immediately with a sleep in there.

private Handler mMessageHandler = new Handler();

private Runnable mSearchRunnable = new Runnable() {
        public void run() {
           if (!isCancelled()) {
               // perform search
           }
        }
    };

then you can put this in you afterTextChanged:

mMessageHandler.postDelayed(mSearchRunnable, 1000);

you can then cancel the thread if the user enters more data with:

 mMessageHandler.removeCallbacks(mSearchRunnable);
like image 192
Martyn Avatar answered Oct 30 '22 18:10

Martyn


You should think about calling cancel(true) to try to shutdown the task while it is waiting or if the call to the webserver is running already. That might save you some process-cycles tho your webserver could be unamused about the broken calls.

If you want to save some gc-cycles you could reuse your SearchCriteria object if that is possible.

Apart from this I can't see any memory leaks. Your objects have short lifecycles and you don't cache them. The only problem that might arise is too many parallel AsyncTasks with running http-requests which will cause an early out of memory. We had that problem once with one app during the monkey-test.

like image 45
marsbear Avatar answered Oct 30 '22 17:10

marsbear


hi this is the link which may be helps you..

http://thinkandroid.wordpress.com/2010/02/08/writing-your-own-autocompletetextview/

like image 2
Akash Thakkar Avatar answered Oct 30 '22 16:10

Akash Thakkar