I have a ListView, which display pictures from Internet, in Adapter's getView method, I will start the Async download thread to download the picture,since I don't know the exact time of downloading finished. As you know, when user touch the screen, the ListView will refresh itself and call Adapter's getView method, then the ListView has been refreshed. But if the user does not touch the screen, even the picture already been downloaded, the ImageView still shows nothing.
So, my question is, what is the graceful way to refresh the ListView after downloading has finished?
You'll need to call notifyDataSetChanged to refresh the underlying views.
You need to load the image in the image view in a separate thread. Thus image will be loaded without touching it.
Related
TL,DR : How can I force the recycler view to call the onBindViewHolder method again, at least for the visible items?
Calling notifyDataSetChanged() will make the list lag for some milliseconds, is there a better way?
Thanks.
I have a layout with an ImageView.
When ever bind is called for the imageview, I send a request to a server in order to get an image.
When the image is loaded, I save the bitmap in the ViewHolder , T variable.
And in the bind method I check if variable.getBitmap() is null or not, and if it is I will set the imageview.
Now If I scroll my list the images are going to be loaded, but If not, the imageviews are still blank, because onBindViewHolder wasn't called again.
Thanks.
notifyDataSetChanged() is definitely the right way. Maybe notifyItemChanged() is even better because it only binds the selected item. If I get your question right, it seems that you do some things on the Main Thread which shouldn't be done there. Remember: Never do potential lengthy actions on the Main Thread, but always use something like AsyncTask.
I think it is a better approach to download the images asynchronously and then cache it, so you don't have to download it every time your Views are recycled. There are libraries for it.
While the images are loading you could show a ProgressBar or something else which signalizes the user, that the image is being loaded.
I have a listview that load images with a adapter. Every time that I scroll the screen, the listview calls the getView to refresh the listview, then the getView loads a image, doing that in my ui thread, locking my screen for a moment.
What I did was to load the images in a AsyncTask class. But the problem is that it take a little bit, and when you scroll you see the wrong image, after a while it louds the right image. I didn't want to have that problem, showing the wrong image for a moment.
I search and saw that there is no way to stop that listview automatic refresh.
What should I do to resolve that problem? Any tutorial would be helpful.
What should I do to resolve that problem?
Set the ImageView to show a placeholder image in getView(), while you fork the task to load the real image. Or, as others have suggested, use any number of libraries for managing all of that for you (and I echo the Picasso recommendation).
I've a list of URLs, each corresponding to an image.
I need to display these images in a ListView.
Currently, my approach is pass this List<String> containing URLs to a CustomAdapter (extending BaseAdapater).
Each row item in the ListView will be inflated with an ImageView.
Then in the getView() method, if currentImageView == null, then I'll start an AsyncTask, which will download the bitmap for that imageList.get(position).
Then in the postExecute(), I'll set currentImageView.setBitmap(downloadedBitmap).
In this manner,from inside the adapter, I'll call AsyncTask one-by-one for each image.
If you think, there is something wrong in this approach then please let me know. Also, please suggest the correct approach.
One pitfall with approach I've found in when AsyncTask for a certain list element is in progress & user scrolls down then back up, the same async task will be called again.
How can I prevent this?
When your views get recycled, the currentImageView will not be null and it will keep displaying the same images. I would suggest using Universal Image Loader. It takes care of all of that for you, with TONS of extra features like caching and what not.
Try this library
Then in getView method, simply add this code
UrlImageViewHelper.setUrlDrawable(holder.image, model.getimageURL(), R.drawable.placeholder);
parameter one is your ImageView, second parameter is Image URL, and the last is placeholder image.
I have a class that extends BaseAdapter, which I use for a ListView. In the getView() method of that class I'm using an AsyncTask with a callback method to download an image (once downloaded, I store it, so I don't have to download it again). When the ListView loads the items first, only the first item displays an image an then starts to change the images (repeatedly displaying the images of the other items). Later also the other items start showing the same behaviour. After a while they stop cycling the images and each item shows the correct images. If I scroll the ListView the items are starting again to cycle the images.
This only happens, if I recycle the convertView parameter, that is passed to getView(). If I don't the images take very long to show up, and I'm afraid I'm creating too much new Views.
Thanks in advance for any advices, to get this working properly.
The simple way to get this going is to dump all your own image loading code and use something that already handles this, like Square's Picasso. There are plenty of alternatives if you do not like Picasso.
Otherwise, your tasks will need to be aware of the recycling, so they do not attempt to update an ImageView that now needs a different image. For example, you could use setTag() and getTag() on the ImageView to store (and retrieve) the URL the ImageView currently needs, and if the image downloaded by the task is some other URL, don't apply it.
But, again, please use an existing library for this. It's 2013: few people should be rolling their own download-the-images-for-use-in-ListView-rows code anymore.
I'm writing an app that shows images in a listview after downloading them from the internet. If an image has not downloaded when getView() is called, I have a placeholder image. The problem with this is if getView() is called before the image is downloaded, and the user does not scroll anymore, the placeholder image will stay there until the user scrolls away and comes back to call getView() on that position again.
I'm looking for a way to listen for the file being created and when it is, update that row. Is this possible? I've googled around, but cannot seem to find anything. I would imagine I would have to call an adapter.notifyDataSetChanged(), but I don't know how to listen for a file being created.