I currently have a gridview that displays some thumbnail images. The problem I am running into is that when I scroll through the images I can see the images switch from old to new as they are being replaced. So, I was wondering how I would fix this. Is there a way to load images that aren't on the screen so when I scroll the user doesn't have to see the change in images?
The best way to avoid that effect is to set the image first to null in the getView() method of your adapter. You can then check an LRU cache if the image is already loaded. If yes, then set it right away, if not then load it asynchronous as a bitmap. Set it to the view and add it to the LRU cache.
Related
I need to show 1000 images in viewpager from DB.The problem is if I fetch all images from DB and try to set those images to adapter,it shows Bitmap out of memory exception since heap size gets exceeded. So,I'm trying other way around which is to load images one by one when the user swipes to next page.I Googled a bit,but didn't find any appropriate solution.so any input on this is highly appreciated.
Here is all that you need : http://developer.android.com/training/displaying-bitmaps/index.html
Load Bitmaps efficiently, LRU cache, etc. etc.
To summarize, you should fetch one bitmap at a time, scale it down using inSampleSizeand use LRUCache. OR, you can use http://code.tutsplus.com/tutorials/android-sdk-working-with-picasso--cms-22149 library
I'm using Picasso Square library in my android application. The app is a very simple one and shows a grid of pictures. When you touch one it opens it in full screen and when swiping to the right the next in line should be displayed.
My problem is that for every swipe, the image is loaded by picasso method:
Picasso.with(getApplicationContext()).load(Properties.IMAGE_URL + i).transform(transformation).centerCrop().fit().into(imageView);
I would like to avoid the load wait time and simply cache the next 2 images to be displayed. how would I go about doing this?
I know that picasso caches the images if they were loaded before. Is there a way to load the next image with picasso without attaching it to a specific ui element to be displayed?
There is a way to do it – use fetch(). You can get more information from this question.
I need to display a list of items each with text and various number of images.
I'm currently using a ListView with custom adapter to show these items. And for each item, I used a HorizontalScrollView with a LinearLayout in it to display the images. In the getView method of the ListView, I read the image URIs of each item and dynamically create ImageViews, then load the images asynchronously. I used a ViewHolder to hold the LinearLayout which contains all the ImageViews of each item.
The problem is, if I scroll down the ListView and scroll back, I'll lost the content of the item, which means I have to load the images again. And most of the images are too large and loads very slow. Actually on my app the screen can show only about 2 or 3 items once, so the scroll happens very frequently.
I have some ideas to improve this, but I'm not sure whether one of them will results better.
Since I'm just showing a thumbnail of each image, maybe I can save the thumbnails into a temp dir and load them dynamically, loading small images will be much faster. And I might have to clear that temp dir when it gets large.
I have at most 9 images for each item, so it might still be slow even if I cache the thumbnails and scroll frequently. And maybe I have to show the list manually instead of using ListView, so each item will not be reused, and the load will happen only once. But, the list will grow large in the future, if I preserve like 100 items in the LinearLayout my app may still crash.
Other better options...
Any advice will be helpful! Thanks!
You can use LazyLoading to display your image. You can use Universal Image Loader for this purpose. What lazyloading does is download an image once, cache it and display the image from cache during subsequent requests.
Context:
I have a main activity holding 6 tabs, each tabs holds a gridview with 30+ images, and around 8 images a shown at any moment (each gridview is scollable).
With these many images I implemented a simple caching system, that is to only cache the latest 25 of them, if new image is needed to display and is not in the cache, I will decode that image from /data/date directory and overwrite the oldest entry in the cache. And before overwriting the oldest entry, I will call Bitmap.recycle() on that.
Problem:
At some point, after displying more than 25 images, old images will start to be recycled. if I were to now navigate back to one of the tab where their Image is no longer in the cache, the GetView method will take care to load the picture again. The Issue is other than the first Item in the Gridview will be calling GetView, rest of the image will never get call, and the Gridview will attempt to display a cached image where it has been recycled already.
Any Suggestion? either to force get view or a smart way to cache image in this scenario?
Much Appreciated
Thanks
I kind of solved this by creating my own ImageView extending the Android ImageView. Then Overrided the onDraw(Canvas canvas) method and added logic to reload cache if cache is gone.
looks Hacky... but worked as wanted. really wish i cna do better than that if there is someone who can teach me. Thanks a ton!!
I've reviewed some posts about lazy loading but I believe my problem is a bit different.
I have a gallery (my class extends Gallery) which displays 20 rather large in size images (400-500K each). I cannot load them all to gallery since I get an OutOfMemory exception.
So, I created an array of 20 Drawables and initially populated the first 9 elements (the images come from the Web) and set all the rest to null. My intention was this: on a fling to the right, fetch element no. 10 and set to null element no. 0. On another fling to the right fetch element no. 11 and set to null element no. 1 to null. Same logic on a fling left.
The problem is I can fling much faster than the elements are fetched.
My gallery has a BaseAdapter and its getView() looks something like this:
public View getView(int position, View convertView, ViewGroup parent){
ImageView imageView = new ImageView();
imageView.setDrawable(imageArray[position];
....
....
return imageView;
}
How do I tell getView() - if imageArray[position] is still null, show a "loading..." dialog and once it is set repeat yourself with the same position?
I don't want to see the imageView empty and then set on the fly. I want to not be able to see the imageView at all until it is set.
Thanks.
Gallery is designed for smooth experience. It will be very bad UI if you block the screen and don't switch to next image until it is fetched. This way user will not be able to fling at all. You should display some loading indicator instead of image while it is loading.
I think your scenario is rather common. You should download images and display them. If you get OutOfMemory you can try to supersample images Strange out of memory issue while loading an image to a Bitmap object.
If there's still OutOfMemory you should remove bitmaps from memory and cache them to SD. So when user flings back you can load images from SD again, it will be fast enough. And memory consumption will be lower. As you suggest you can have 10 most recent images cached in memory and others cached on SD.
You can take a look at my sample code Lazy load of images in ListView. Actually it's a ListView adapter but you can apply it to gallery with minor modifications. I think it will do exactly what you need.