What's LazyList? - android

I can't find in any really credible source explaining what LazyList is. Anyone?

Lazy List is lazy loading of images from sd-card or from server using urls. It is like on demand loading of images.
Images can be cached to a local sd-card or your phone's memory. URL is considered the key. If the key is present in the sd-card, images get displayed from sd-card, otherwise it downloads the image from the server and caches it to a location of your choice. You can set a cache limit. You can also choose your own location to cache images. Cache can also be cleared.
Instead of the user waiting to download large images and then displaying them, lazy list loads images on demand. Since images are cached, you can display images offline.
https://github.com/thest1/LazyList. Lazy List
In your getview
imageLoader.DisplayImage(imageurl, imageview);
ImageLoader Display method
public void DisplayImage(String url, ImageView imageView) //url and imageview as parameters
{
imageViews.put(imageView, url);
Bitmap bitmap=memoryCache.get(url); //get image from cache using url as key
if(bitmap!=null) //if image exists
imageView.setImageBitmap(bitmap); //display iamge
else //downlaod image and dispaly. add to cache.
{
queuePhoto(url, imageView);
imageView.setImageResource(stub_id);
}
}
An alternative to Lazy List is Universal Image Loader
https://github.com/nostra13/Android-Universal-Image-Loader. It is based on Lazy List (it works on the same principle), but it has lot of other configurations. I would prefer to use Universal Image Loader because it gives you more configuration options. It can display an error image if a download failed. It can display images with rounded corners. It can cache on disc or memory. It can compress an image.
In your custom adapter constructor
File cacheDir = StorageUtils.getOwnCacheDirectory(a, "your folder");
// Get singletone instance of ImageLoader
imageLoader = ImageLoader.getInstance();
// Create configuration for ImageLoader (all options are optional)
ImageLoaderConfiguration config = new ImageLoaderConfiguration.Builder(a)
// You can pass your own memory cache implementation
.discCache(new UnlimitedDiscCache(cacheDir)) // You can pass your own disc cache implementation
.discCacheFileNameGenerator(new HashCodeFileNameGenerator())
.enableLogging()
.build();
// Initialize ImageLoader with created configuration. Do it once.
imageLoader.init(config);
options = new DisplayImageOptions.Builder()
.showStubImage(R.drawable.stub_id)//display stub image
.cacheInMemory()
.cacheOnDisc()
.displayer(new RoundedBitmapDisplayer(20))
.build();
In your getView()
ImageView image=(ImageView)vi.findViewById(R.id.imageview);
imageLoader.displayImage(imageurl, image,options);//provide imageurl, imageview and options
You can configure Universal Image Loader with other options to suit your needs.
Along with LazyList/Universal Image Loader you can view this website for smooth scrolling and performance.
http://developer.android.com/training/improving-layouts/smooth-scrolling.html.

AFAIK, I'll explain you with the example
If you list contain lot of images with Text, it will take some time for your list to load because you need to download images and you need to populate them in the list. Suppose if your list contains 100 images It will take lot of time to download each image and to show it the listitem. To make the user wait until the images loads is not user friendly.
so What we need to do. At this point of time lazy list comes into picture. It is the idea that let the images be loaded in background and show text mean while.
Everybody know that listview recycle its views for every view. i.e if your listview contains 40 elemtns then listview won't allocate memory for 40 items instead it allocate memory for the visible items, i.e say you can see only 10 items at a time. so listview will allocate 10 items meemory.
So When ever you scroll the view, then the view will refresh. because of the you'll lose your reference to images and you need to download them agian. in order to avoid that, caching comes into picture.
This example is based on my knowledge in listview, I am not saying this is only correct. There might be wrong in the answer, if any body find feel free to inform me.

I think this is the other way around. AFAIK, Lazy Loading is the definition, where you actually load the data only when you need it, and it's a good design practice.
So I believe the same applies for this, only this time it's being referring to the List View.
If I'm wrong, please correct me.

The best example of lazy list is facebook notifications,messages,requests. when you scroll then data will be load.

Related

Performance: use Webview to display images instead of ImageView

In my Android Activity, I want to display about 10 images from web. Normally, I have to create 10 ImageView to display each image, but ImageView may cause Out of memory exception. So I decide to use 10 WebView to display image. It worked great.
But I don't know how performance of WebView, can anybody advise me how performance of 10 WebViews and Can I use this method to display images?
WebView occupies more space in memory then image view . you won't get proper scaling in webView just by simply displaying images. Webview can be faster in popping image to Ui but its not the efficient way .
You can try Volly which has in build tool for image downloading,caching and scaling and i can insure you its quite fast also.
All you need to do is add the Volley library to your project and replace ImageView in your XML layout with com.android.volley.toolbox.NetworkImageView.
Add the following variables to your Activity class:
private RequestQueue mRequestQueue;
private ImageLoader mImageLoader;
Create the objects in the onCreate() method of your Activity:
mRequestQueue = Volley.newRequestQueue(context);
mImageLoader = new ImageLoader(mRequestQueue, new ImageLoader.ImageCache() {
private final LruCache<String, Bitmap> mCache = new LruCache<String, Bitmap>(10);
public void putBitmap(String url, Bitmap bitmap) {
mCache.put(url, bitmap);
}
public Bitmap getBitmap(String url) {
return mCache.get(url);
}
});
Then download the image the getView() method of your Adapter class:
NetworkImageView image = (NetworkImageView)view.findViewById(R.id.image);
image.setImageUrl("http://someurl.com/someimage.png",mImageLoader);
In production code, you would use a global instance of both the RequestQueue and ImageLoader classes, and your onCreate() method wouldn't be cluttered as it is in this toy example.
I wouldn't use a webview to display images, though of course it can be done. If you really want to see which way is "faster", you can try out ImageView, NetworkImageView and WebView to load a large image and get a rough time estimate with the System.nanoTime() method.
Do you display 10 images at the same time ?
If yes, the size of the image view must be relatively small, so you can use small version of your images and avoid out of memory errors (or download the real size but create in memory a small version).
If not, you should use a ListView or GridView or ViewPager or something that recycle the views. You only get a couple of them in memory at the same time and avoid out of memory errors.
Furthermore, there are excellent libraries to display download and display images, for instance Universal Image Loader will do everything in the background, resize the image to the required size, you can activate the memory cache / disk cache, etc.

Lazyload with a Bitmap Array

So my app lists all the files and folders in a given Dropbox folder. They are listed in a custom ListView using an adapter.
Currently I use drawables for the image and folder icons. I loop through the Dropbox folder structure and add the needed drawable to a Bitmap array. This is done in an Async Task (doInBackground).
I then call the Adapter in the PostExecute like this :
adapter = new ImageAdapter(this, pix, paths);
lstView.setAdapter(adapter);
This then shows all the files and images (with default drawable icons) in the ListView.
The next step I want to do is start loading the thumbnails from dropbox.
So for every image in the List, I want to replace the drawable with a thumbnail retreived from dropbox.
Again this should be done in an Async task so the user can still scroll through the listview.
With dropbox, you can load thumbails like this:
if(fileInfo.thumbExists)
{
file = fileSystem.openThumbnail(fileInfo.path, ThumbSize.XS, ThumbFormat.PNG);
Bitmap image = BitmapFactory.decodeStream(file.getReadStream());
thumbs.add(image);
file.close();
}
In the code above, thumbs is a Bitmap Array.
I was planning on using Universal Image Loader or Picasso. But you cannot pass in a Bitmap Array into either of those. It has to be a URL or URI.
How can I achieve this? I'm guessing I need another async task, but I'm not sure how to update my adapter.
Considerations:
I don't want to wait until all thumbnails are downloaded before
starting to display them
Are there memory considerations if there are lots of thumbails?
Can you only display thumnails in the Visibile part of the
listview, and start loading more when they scroll?
Remember - I am using an array of Bitmaps, I don't have any URLS. Would I be best saving each Bitmap to the sd card and then using UIL or Picasso to load using the URI? But how would you know which images went to which position in the ListView?
SO the steps in my code would ideally be:
-Load the Listview with the files and folders with dummy images (already doing this!)
-Get the thumbnails from the decodeStream and load into the Bitmap Array
-Load the thumbnails into the correct position into the ListView
For each row of the list view, run a separate thread to download and show the thumbnail image.
I guess, you can avoid the use of a bitmap array and directly feed the downloaded image to the list view row.
I) Modify your getView() call back of the adapter like the one below:
ImageView thumbnail=Container.findViewById(R.id.thumbnail)
loadImageInBackground(thumbnail,URL).execute();
II) loadImageInBackground will be a class that implements AsyncTask
a) data members: ImageView thumbnail,String URL
b) Constructor: Initialize these data members with instances passed.
c) onPostExecute: Set a dummy image to the thumbnail here, that will appear until the required image is downloaded.You can even set an animating image here to give it a better feel.
d) doInBackground:
mUrl = new URL(strUrl);
HttpURLConnection conn = (HttpURLConnection) mUrl.openConnection();
conn.setDoInput(true);
conn.connect();
InputStream is = conn.getInputStream();
bmImg = BitmapFactory.decodeStream(is);
is.close();
}
catch (IOException e)
{
e.printStackTrace();
}
e) onPostExecute: associate the this.thumbnail to this.bmImg.
This way for each row of your list view an object of loadImageInBackground class will be initialized and will download the image from URL and set it to the image View container of the corresponding row.
The images will be displayed on the Thumbnail as soon as they are downloaded. There will be no Blocking, I mean, the user can interact with the app even when the images are being downloaded.
If you have implemented a lazy loading methodology, then this approach will not cause any outOfMemory exceptions in any case.And also, new images will only be downloaded when the user scrolls.
Point II.c provides for setting loading animation/image on the thumbnail until the actual image has been downloaded.

Most efficient method of working with a large number of images in Android

I'm working on a music player app for android and am trying to find the best way of dealing with images. I'm loading artist images from the web, and album images either from the MediaStore or the web depending on the circumstances. I will need to add either set of images (artist or album) to listViews at different times.
Storing the images in memory (HashTable) would make loading very quick, but could become impractical if the user has a very large music library.
However I can't load them on an "as needed" basis because I need to bind them to a listView. In addition, I have a notification that displays the artist image and provides navigation controls. If I wait to load the image when the user clicks the next button, it might not load before the notification view updates.
Is the best approach to connect to the Net on first load and then save the files locally, and then load them as needed? If I do it this way, will the image be loaded quickly enough to keep up with a user fast-clicking the next button and refreshing the artist image view?
Thanks,
Use a listview or gridview to display images.
You can use https://github.com/nostra13/Android-Universal-Image-Loader Universal Image Loader to load images either form MediaStore or from the web. Uses caching. Based on Lazy Loading but has more configuration options.
In you adapter contructor
File cacheDir = StorageUtils.getOwnCacheDirectory(a, "UniversalImageLoader/Cache");
// Get singletone instance of ImageLoader
imageLoader = ImageLoader.getInstance();
// Create configuration for ImageLoader (all options are optional)
ImageLoaderConfiguration config = new ImageLoaderConfiguration.Builder(a)
// You can pass your own memory cache implementation
.discCache(new UnlimitedDiscCache(cacheDir)) // You can pass your own disc cache implementation
.discCacheFileNameGenerator(new HashCodeFileNameGenerator())
.enableLogging()
.build();
// Initialize ImageLoader with created configuration. Do it once.
imageLoader.init(config);
options = new DisplayImageOptions.Builder()
.showStubImage(R.drawable.stub_id)//dummy image
.cacheInMemory()
.cacheOnDisc()
.displayer(new RoundedBitmapDisplayer(20))
.build();
In your getView()
ImageView image=(ImageView)vi.findViewById(R.id.imageview);
imageLoader.displayImage(imageurl, image,options);
You can also use https://github.com/thest1/LazyList. Also uses caching.
Also use a ViewHolder in listview or grdiview. http://developer.android.com/training/improving-layouts/smooth-scrolling.html.
Load your images from local file storage or MediaStore in the getView() function of your ListView's ListAdapter or SimpleListAdapter. The adapter will take care of only calling getView() when necessary for the item(s) needed by position. Your system will be fast enough to load the images in this manner when they are needed.
You will have to fetch all images from the web at an earlier time and store them in the local filesystem so they are available for display by the ListView.

caching disk image

I am trying to use a disk cache (not a memory cache) so i download my images from an urls and put it in a grid view. I want to download my images only one time.
I found this example (bitmapFun) in google site: http://developer.android.com/training/displaying-bitmaps/cache-bitmap.html
I found this example a bit complicated.
There are many objects in util package (AsyncTask, DiskLruCache, ImageCache, ImageFetcher, ImageResizer, ImageWorker, Utils)
Is there a way or a tutorial that show how can i use a disk Lru cache without using all those object.
I don't want to resize my image and i was not able to remove ImageResizer class.
Here you have good answer :Android image caching. Quotation :
"Consider using Universal Image Loader library by Sergey Tarasevich. It comes with:
//Multithread image loading. It lets you can define the thread pool size
//Image caching in memory, on device's file sytem and SD card.
//Possibility to listen to loading progress and loading events
Universal Image Loader allows detailed cache management for downloaded images, with the following cache configurations:
UsingFreqLimitedMemoryCache: //The least frequently used bitmap is deleted when the cache size limit is exceeded.
LRULimitedMemoryCache: //The least recently used bitmap is deleted when the cache size limit is exceeded.
FIFOLimitedMemoryCache: //The FIFO rule is used for deletion when the cache size limit is exceeded.
LargestLimitedMemoryCache: //The largest bitmap is deleted when the cache size limit is exceeded.
LimitedAgeMemoryCache: //The Cached object is deleted when its age exceeds defined value.
WeakMemoryCache: //A memory cache with only weak references to bitmaps.
A simple usage example:
ImageView imageView = groupView.findViewById(R.id.imageView);
String imageUrl = "http://domain.com/image.png";
ImageLoader imageLoader = ImageLoader.getInstance();
imageLoader.init(ImageLoaderConfiguration.createDefault(context));
imageLoader.displayImage(imageUrl, imageView);
This example uses the default UsingFreqLimitedMemoryCache.

Save image to sdcard from imageview

I have listview having customized some textview and one imageview. When I long click on item I have store that item information to the database but the question is how to store image in sdcard and store the relevant path to the database. The image alread download as cache now I don't want to re-download that image.
Is there way to store that Image to the sdcard.
I am using this example to download the images for listview https://github.com/thest1/LazyList
Edit
I got solution
no need to extra process when using this example. Just store the web path of image into the database and pass that imageview into the ImageLoader object with path it'll use the cache images if the image was exist for same URL
No Need to extra process, Using this example it'll will care for future usage also for same URL of image. This will get from the cache directory if the image found that use that image otherwise download it and then use it.
If you use Prime the caching will be transparent, when you request the image again it will grab it from a memory cache if available or a disk cache automatically. It also is really easy to get images with.
You can save your bitmap which you get via Bitmap bitmap=memoryCache.get(url); using save-file-to-sd-card.
You can also get the bitmap from the ImageView(if you want) like:
//say your ImageView object is i;
i = (ImageView) findViewById(R.id.img);
Drawable d = i.getBackground();
Bitmap bitmap = ((BitmapDrawable)d).getBitmap();

Categories

Resources