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.
Related
So I have this view that moves throughout different views that I have. I tried moving it using a new thread but I got "Can't access View from a different thread than it was created on", so I was like, "whatever just move it to the main thread then". So, I currently have runOnUiThread(this) (The class implements Runnable).
Now, it says:
Skipped x frames! The application may be doing too much work on its main thread.
I googled for a loophole and found that I can use a Handler to do this, which I was able to follow until it was talking about implementing a task. They used a task called PhotoTask and not knowing what it was or where it came from, I just got lost.
So can somebody either explain the Task or tell me another potential way around this?
Code that's causing the error (Note there are more if statements, but they're all the same on the inside as this one:
while (lackees[i].getTileX() < lackees[i].getDestX()
&& lackees[i].getTileY() < lackees[i]
.getDestY()) {
lackees[i].setTileX(lackees[i].getTileX() + 1);
lackees[i].setTileY(lackees[i].getTileY() + 1);
getTileAt(0, lackees[i].getTileX() - 1,
lackees[i].getTileY() - 1).removeView(
lackees[i]);
getTileAt(0, lackees[i].getTileX(),
lackees[i].getTileY()).addView(lackees[i]);
Progress Update #1:
It seems that wait() is better to use then Thread.sleep() but I still get frames lost, just not as many.
Your question is not very clear.
What do you mean by "So I have this view that moves throughout different views that I have".
Handler are mainly used to communicate between 2 threads.
PhotoTask in given link is simply an object/model used to send message from 1 thread to another via Handler.
If you want to update a view, you need to do this in main/UI thread alone. If you want to do some UI update from a separate thread you need to inform the default UI thread handler by passing the operation to be done as a separate runnable instance via runOnUiThread/ view.post/ handler.post.
I can clarify on how to use shared views without using any handler or thread if this is what you need.
I have a gridview of bitmaps of very large number. To prevent out of memory error I only load a number of bitmaps and using onScrollListener I recycle the non nessecary bitmaps and create the ones that need to be shown. The loading bitmaps proccess is done in async task. This is the update method which is called every time the scrolling stops
AsyncCaller asyncCaller;
public void updateImageList(int first, int last){
if(!asyncCaller.isCancelled()){asyncCaller.cancel(true);}
asyncCaller=null;
asyncCaller=new AsyncCaller();
asyncInput input=new asyncInput();
input.first=first;
input.last=last;
input.id=Integer.toString(asyncId);
asyncId++;
asyncCaller.execute(input);
}
where asyncCaller is a class variable.
This code causes a NullPointerException at the asyncCaller.execute(input); line. Can someone tell me why since I assing to asyncCaller a new instance before calling execute?
I used asyncCaller as class variable in order to be able to cancel it if a new scroll has been made before the currently running AsyncTask has finished. No reason to keep it running since those bitmaps are no longer needed.
If I use asyncCaller as a local variable in the updateImageList method there is no way to cancel the currently running instances...correct?
EDIT: the question is pointless since the problem was a simple error from my part. I leave the question with my code corrected and working for refference for anyone looking for something like that
replace this line
asyncCaller.execute(input);
with
new AsyncCaller().execute(input);
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);
I'm developing a custom ListView, which uses a custom ArrayAdapter and custom elements.
Actually I'm displaying a list of tweets.
I want to display for every tweet the time elapsed from the creation, exactly like twitter.
I wrote a timer that calls a method on every list element. This method calculate the elapsed time and set it on a TextView on the element with setText().
Problem is that I can't get the list update. The values change only when I add a new element or manually scroll the list.
If you need code ask freely.
EDIT:
The answer of Nick Caballero is correct, but it wasn't working.
I have already tried that code. The problem was in the timer and in a try catch with a generic Exception.
The timer was trowing a CalledFromWrongThreadException. The solution was to use a runOnUiThread for its operations.
Calling notifyDataSetChanged does additional operations that are not necessary here. Updating the view with the time elapsed relative to the timestamp of the data does not imply a change in the data.
See https://stackoverflow.com/a/2679284/724068 for how to loop through the visible views in the list. You can then extract the view containing the time elapsed and update accordingly. Since you have to run this every so often to keep the UI up-to-date, you will have to use a Runnable, posting to the main Looper every second.
Also see https://stackoverflow.com/a/9987616/724068.
You might want to try calling invalidate() on the control once its updated. Code would be helpful though.
In my android application the scenario is this -
I have several images stored in the SD card.
Now in my app I have an Image view and I have to update this image view continuously
like a slide show is running. This has to be done by fetching images one by one from SD card and setting them in the same ImageView. Also the interval of image change in ImageView is fixed.
So I have a cursor which stores the information for fetching these images.
Now I am wondering what should be my approach for moving the cursor one by one and fetching images from SD card and setting them in my ImageView.
Should I use Timer Task and Timer or should I go with Handler or something else?
Please help as this is initial point of my app and I want to start in the right direction.
Since you're retrieving large data from the SD card, it might be best to use a thread to retrieve/decode the bitmap.
In this case, a Timer would be useful because it runs on it's own Java thread for scheduled periods of time. However, you have to keep in mind that you can't update a UI element from a non-UI thread. Thus, you'd need a syncing element in place for when the bitmap is fully loaded to finally put the decoded bitmap in to the ImageView. In which case, you would need to use Handler anyway to send message queues to the UI thread.
Thus, I'd probably recommend using a combination of Handler and AsyncTask. Create an AsyncTask class that retrieves and decodes the bitmap in doInBackground(). Update the ImageView in onPostExecute(). Use a Handler to create and execute a new AsyncTask ever Nth milliesecond (whenever you update the view).
One advantage to this is it keeps all image retrieval in one class. You can open the cursor, retrieve, close it. This is safer than keeping a long-running cursor open.