Best practice to use AsyncTask in autocomplete? - android

I am using Async task to populate auto-complete suggestions from server.
Problem:
when user types and removes the text in edittext so many times.
lets say he typed: cofee > cof > coffee >coffee late .... etc for so many times.
for each text changed after 3 keyword(threshold) i am initializing an asynctask and ask for result.
so in current scenario i have so many threads running in background. so some of my latest async threads are waiting for there chance.
Whole this make my app very slow.
What can I do to tackle this problem?

If it is possible to load entire data from server at beginning...then you can avoid calling asynctask repeatedly and fetching the data from server. This will improve performance of you app. If data displayed in Listview is String, following link show how to filter it:
http://www.androidhive.info/2012/09/android-adding-search-functionality-to-listview/
And if custom object is used in ListView adapter, try:
Filtering ListView with custom (object) adapter
Hopefully this helps.

You should cancel the current task before issuing a new one. Use AsyncTask#cancel(true) for that and make sure that the execution of the task can be quickly stopped. This means correct handling of interruption and frequent checking whether the task was cancelled in the body of AsyncTask#doInBackground.
And you cannot execute again the AsyncTask you have cancelled. You have to create a new one. (Trying to execute it again leads to IllegalStateExceptions)

It worked for me by cancelling the task each time you change the text (if it is still running).
You need to define your request once outside the listener(private for the class), and then start your listener function by (if your request is not finished, then cancel it).
define your request out side the function
private YourSearchTaskClass YourTaskReq = new YourSearchTaskClass();
then start your addTextChangeListener/afterTextChanged by this
if (YourTaskReq.getStatus()!= AsyncTask.Status.FINISHED)
YourTaskAvReq.cancel(false);
YourTaskReq= new YourSearchTaskClass(keyword);

Related

How to make a ThreadPool?

I am making a map app with OnClick marker creation. I am using simple AsyncTask class to get the street address of the LatLng i clicked so i can set a marker and save an Address object into list for future onMarkerClick intent, so i can display address into second activity, and of course database backup in onDestroy. Problem is that AsyncTask is an option when i create a marker and click on it. If i create 2-3-4 or more, they don't build up into a queue and i lose the first or all of them except the last one. I am reading now about ThreadPool and AsyncTask.THREAD_POOL_EXECUTOR but i really find this very difficult. Is it ok to ask for a simpler explanations or/and a code sample?
Stuff i know ATM:
AsyncTask is not an option cause it manages only a single background thread.
Thread is harder to implement but gives control to priority.
I need to create a new thread on every click or make a queue of tasks to get this done.
Geocoder class was an option but doesn't work for me.(bad formatting, random unavailability).
The Android developer documentation has the appropriate trainigs for Thread Pool. Using this, you can also communicate with the UI thread so you can (in your case) be able to manipulate/update markers and set listeners to it.

How to increase listview performance?

I have a scenario where i have to do following task:
1. populate a list-view.
2. perform database operation which is very time consuming task.
3. database processing/operation time is sometime unpredictable.
I have used listView using holder pattern, now it is working faster than earlier but still taking significant time. What else i can do to improve the performance.
I have an idea but i am afraid whether it will be good to implement or not. Idea is to put the database operation in AsyncTask and update my listview there only.
But i am afraid of doing so is because my listview is totally dependent on database result. So i can display something on Listview only when i am done with DB operation
Please suggest is using Async task will be good approach and please suggest any other idea.
Using the Holder approach is good. Use that in your adapters always. Make sure you are reusing the convert views as well.
Using an AsyncTask is the best option. But you don't have to wait for the entire operation to complete. Read up on how AsyncTask works. Use the publishProgress() method in your doInBackground() of the AsyncTask to give batches of data to your list.
For example, if you have to process 100 rows, process 10, then do a publishProgress() which will update the list with those 10 rows. When you process the next batch, update the list with publishProgress() again.

Calling AsyncTask from AsyncTask

Although I have not tried it yet, but from theoretical point of view I'm asking this question just to clear my doubts.
I have a scenario like:
1. Send a request to a server and receive JSON response. For this I'm using AsyncTask as there can be delay in receiving response.
2. From this response fetch an image URL.
3. Using one more AsyncTask, call the image URL and fetch the image. (Again may take time to fetch image)
So do you think using of 2 AyncTask just to get that image is inefficient.
OR, in step 1, instead of using AsyncTask, run the code sequentially and set Timeout instead.
Please suggest.
I'm going to go ahead and suggest this as an answer, which was originally in my comment:
Just fetch the image synchronously in the same AsyncTask that you're fetching the JSON from. For example:
doInBackground(Void...params){
//fetch JSON
// once JSON is fetched, fetch image
}
Not sure how you want to structure this exactly, but documentation says:
execute(Params...) must be invoked on the UI thread.
http://developer.android.com/reference/android/os/AsyncTask.html
so you cannot execute new async task from other async task background method.
even if you tried doing this from progress method, then since HONEYCOMB asynctasks are serialized, so your second async task will get queued anyway - you would have to use THREAD_POOL_EXECUTOR to make it run parallel.

Downloading data in separate thread before initializing a ListView

I'm having issues with multithreading in my application. I know there are many posts on Threads/AsyncTasks/etc, but none seem to address my specific problem.
Basically, I get a query string in my search Activity, then send it to my results Activity, where the string is used as a SQL query, the results are returned as an array of JSON objects, then I display these objects in a ListView (which is part of the results Activity). All of my SQL connection and retrieval is done in a separate class that I call at the start of the results Activity.
MySQLRetrieve data = new MySQLRetrieve();
ArrayList<Tile> tiles = data.getResults(nameValuePairs, isLocationSearch);
The above code is how I get the SQL response and convert into an ArrayList, which I then use the populate my ListView with. getResults() takes care of all of this.
I already have separate threads working to download images into the ListView, but what I can't get to work is getting the SQL query and result to run in it's own Thread. What I want to achieve is this:
User enters search query in search Activity.
Intent is sent to results Activity, and it starts immediately.
ProgressDialog (just the animated spinner thing, not a loading bar) displays while the SQL query is taking place.
ListView populates with objects from the JSON array, lazy loading images as they come.
I have steps 1,2, and 4 working well, but 3 is the problem. I've looked up AsyncTasks, which seem to be the answer, but I just can't get them to work. Does anyone have a solution to this problem? I need to do this, so when starting the results Activity, the UI changes immediately to the results Activity and doesn't have to wait until the SQL response is returned.
And yes, I've already read the painless-threading post.
Thank you.
I would recommend against creating that ArrayList<Tile> to reduce memory consumption (and code size) and instead directly bind the SQLite Cursor to the ListView using a CursorAdapter.
That alone might just increase the performance enough that you don't need to do any async loading.
If you still want async loading, check out the LoaderManager framework (available since Android 3.0/ API level 11, with Android support package down to 1.6/4) which will automagically do asynchronous loading of your Cursor -- either using the built-in CursorLoader (if you happen to have a ContentProvider), or the SimpleCursorLoader created by a fellow SO user (if you don't).

Android: Update Listview after Thread loads data from the net

I like that my GUI appears immediately when the user starts the app.
Then some data (text, pictures) gets loaded in the background (like YouTube app).
The ListView and Gallery gets updated automatically with this new data.
I initiate my ListView, start a Thread and load the data... and then the ListView does not get updated!
Several people told me I should use notifyDataSetChanged().
But I cannot place this command in my Thread (just unknown).
Any ideas?
I have this same problem... and I got excited when I came across this question. But no answer? :-(
After, letting the problem sit for about two weeks I found the solution here:
Long story short:
Quote from above link:
We must use a Handler object because
we cannot update most UI objects while
in a separate thread. When we send a
message to the Handler it will get
saved into a queue and get executed by
the UI thread as soon as possible.
Once you check out the code you see get what the author is saying.
NOTE: Even with a handler, Android may not let you update a view object from the thread's run() method.
I got this error:
05-31 02:12:17.064: ERROR/AndroidRuntime(881):
android.view.ViewRoot$CalledFromWrongThreadException:
Only the original thread that created a view hierarchy can touch its views.
To get around it I updated an array of data in my run() method and used that array to update the view in the handler's handleMessage() method.
I hope this helps others out there.
You may use the slowAdapter to refresh the View:
SlowAdapter slowAdapter = new SlowAdapter(this);
list.setAdapter(slowAdapter);
slowAdapter.notifyDataSetChanged();
Just found it myself while reading this thread and trying around.
Short: AsyncTask's method onProgressUpdate can touch the view: http://developer.android.com/reference/android/os/AsyncTask.html#onProgressUpdate(Progress...)
Background: I needed to call requery on my cursor so a ListView kept being updated while the task fills the database. The requery call made in doInBackground failed with the mentioned CalledFromWrongThreadException but same code in onProgressUpdate works.

Categories

Resources