I have high quality, rich in color images in my server. I am displaying them in ListView in small ImageViews. After the user selects item, he gets fullscreen of the selected image. In this way after selecting image, the image loads quickly, as it was already loaded and I save them in cache.
The problem is that the whole List on first startup is loading pretty slow, as each item needs to be downloaded. Is there any way I could reduce the image loading in ListView? In my vision the ListView should load pretty quick, and after selection the image may load longer. I know I could optimize this by passing low quality, resized images from server to list. And after selection pass high quality image url. But this is a very big job, as I have ton of images and resizing each one of them would be a pain.
Any ideas how could I optimize this even a little?
Update: I guess my question wasn't clear enough. There is no problem with ListView, or image loading. I do not hung user at some "loading" screen, I do asynchrounsly load images, and I do simbolize that images are being loaded for each item in ListView. But with slow internet connection, the thumbnails just stay there for too long, I think the user would just quit the app... I'm looking for a way to optimize loading process. Loading just resized Images would be great, something like: 50kb for ListView and fullsize for SelectedView. I think in such way the user experience would be much better.
https://github.com/nostra13/Android-Universal-Image-Loader. Universal Image Loader is Asynchronous, uses caching and is a improves version of LazyLoading.
You can cache images in memory or disc. You can also provide custom folder to cache images. Universal Image Loader also provides you with other configuration options.
https://github.com/thest1/LazyList. you can also use lazy loading.
For performance and smooth scrolling use ViewHolder.http://developer.android.com/training/improving-layouts/smooth-scrolling.html.
http://www.youtube.com/watch?v=wDBM6wVEO70. The talk on View Holder for listview.
You can use the universal image loader. It enables you to download the images on a background thread. Basically you display the ListView with some default thumbnail and when each image is downloaded the UIL replaces the thumbnail with the real image.
That way the user will not be trapped while the images are downloading, but showing all the thumbnails will surely require downloading all the big images until you start serving small variants for the images.
Related
I'm trying to replicate the functionality of Facebook's image upload. To briefly describe it you click the Photo button from the main screen of the app you are taken to an image picker that will let you select up to 30 images. Once selected the images load in some kind of list view that allows you to add a caption, remove the image from the list, or do some other Facebook-y things. If you scroll around the list can move very quickly, and if you only have 5-10 images you generally spend little to no time waiting for items to reload.
Right now I have a recycler view and am using Picasso to load the images from disk, resize them, and then display them. This works, but it's not smooth or fast. Even if I only have five or six images loaded they don't come up instantly if I scroll from the bottom back to the top. I have tried increasing the LRU Cache size in Picasso, but that didn't do anything at all. It seems like the scaled image isn't getting cached so it has to be scaled to fit the screen width every time. That's just my guess though.
Any suggestions on how to get this to run more smoothly?
I am getting URL string of image in one response, Then i am downloading those images and converting tobitmaps then displaying in listview.
Here my question is in future listview items may increase upto 50000,in this case how can i handle data in listview for smooth scroll without giving ANR Exception.Please provide some sample code.
Dont Load All Images At a Time.... It will cause OutOfMemoryException..you can load images in number of pages from URL....
To download images from URL you can use Picasso library...
It helps you to avoid OutOfMemoryException and store cache of images too..
You can use LAZY LOAD... and you can try this code for download images...
Picasso.with(context).load(URL).fit().centerCrop().into(imageView);
Simple answer dont make a listview so big. 50K elements in a single screen is never a good idea in any scenario(web, desktop or mobile). My suggestion is to have some sort of pagination just like in websites. As for the images like #Prag suggested above use lazy loading for showing images. In my app I used Universal Image Loader and find it extremely useful for showing a large number of bitmaps.
I have a bunch of images that are displayed in a list view (one per row). The image file I have is a pretty large resolution so I'll need to scale it down to be shown in the list view.
So, my questions is...is it faster to store two images (one regular and one thumbnail) so nothing has to be scaled on the fly OR is it faster to simply allow android to scale this larger image upon list creation?
Thanks!
Nick
The best approach depends on your particular use case. If you really want to resize the image to a thumbnail level (e.g. 150x150) and don't plan to have more than about a 30 images to display, the best approach would be to just keep a cache of the Bitmaps in memory without writing them to disk (at a cost of about 3 MB of memory for the 30 images). This way your ListView won't stutter while you scroll images in and out of the screen. You can of course keep the full version and display that when the user taps on the ListView item.
If you want to display a higher resolution version in the ListView, then you might have to get creative. Remember that you don't have much time to render each individual ListView cell to keep a smooth scrolling experience, and that decoding a large image file will take time, even if you're downsampling it and resizing it; the initial decoding time is the same, the only difference is the size in memory. In this case then it might be convenient to keep both the original and the smaller size version in disk to reduce the stuttering as you scroll.
Store two images to avoid your users having to wait to get the fullsize of every image even though all they're looking at are thumbnails, unless the images are bundled in with the app (i.e. not downloaded on the fly).
I have an ASync task that D/L the images for the list view.
Have the listview and the listview adapter implementation working fine.
My question is:
After D/L the images from the web...
1. Should I save it into a temporary directory and load it from there? OR
2. Should I keep it in memory? But in this case might consume lots of memory since the list size can be big.
3. If I have an image that was U/L before to the server, I need to show it in the listview as a small image (sample?). Should I jsut put the image in the imageview? Should I process the image and scale it?
Yoav
I would keep the images in memory in a WeakReference. This means that the images will be released if the OS runs low on memory. In addition, you could save them to the SD card, so that when the images have to be reloaded, they will appear faster. You can check this thread Lazy load of images in ListView for some more hints.
Scaling the images is highly recommended for performance.
For anyone who's wondering, the gallery is http://www.spore.com/sporepedia.
My app uses the Spore API to get the 100 newest creations, then displays them in a GridView. The text data about the creations is easy to store, but the images present a problem.
As far as I know, I can either keep the images in a Hashtable or grab them every time they are viewed. Neither of these will work - the Hashtable quickly presents an OutOfMemoryError, and the constant reloading causes a lot of load on the server and a lot of lag on the client.
Is there a better way to store the images?
First Don't get 100 at a time, there is no way your displaying 100 images in a gridview and having them be a usefully visible size. Retrieve the images asynchronously and get a screen full or a screen and a half at a time. I'm guessing you can display 6 to 9 images of a decent size per screen with supporting text/UI elements, you may even want to choose how many to display based on the handsets screensize/resolution. So you should probably be getting 9 to 12 images at a time.
Second, i don't know what resolution these images are coming in at, but it sounds like 'big'. If the API supports it receive only a thumbnail version for you grid view. If not, what i would probably do is: when you receive an image from the API, first create a new image scaled down to the size needed for your thumbnail that goes into the grid view, keep this in memory. Then create a new image scaled down to the size you would need for your 'detail' screen (if you have one) and cache this to the SD card and free it from ram as well as the original source image, this scaling should probably occur in a separate thread to avoid it impacting the responsiveness of your UI thread. Depending on the usage pattern, I would probably also cache the thumbnails to the SD card so it would be cheap to free the ram they use in onStop/onPause and reload them in onStart/onResume. IT also sounds like you downloading a 'top 100' or something of the sort. Since i wouldn't expect an entires new top 100 on every application use you could save a lot of network traffic by caching the images and information to the SD card and only downloading new entries each time the program runs.
Alternatively a process like:
Receive Image -> Scale in place to detail size -> cache detail size -> scale detail size to thumbnail size in place -> display thumbnail in gridview while caching thumbnail asynchronously
Would use even less memory since there is only ever 1 copy of the image in memory, but it would slow the response of the gridview as the image has to be scaled twice before it gets displayed. It may be fast enough to not matter or you may be able to play tricks with the grid view by having it display the large image (scaled internally) while the thumbnail is generated in the background, switching the gridview to the thumbnail when its ready. You'll just have to try it to determine if its fast enough.