Performance: use Webview to display images instead of ImageView - android

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.

Related

Updating List View after Async Task finishes Android

I have a List View of images.
If no image exists in the local cache, the placeholder image will remain in place of the image.
Then an asynchronous task is run to download the image from a server.
Once the async task finishes I set the imageView bitmap to the downloaded image.
Then I call notifyDataSetChanged()
The problem is that I need to scroll down and scroll back up for each cell to show the new image that has been downloaded. It doesn't update the cells automatically.
So I have:
public class ImageLoadTask extends AsyncTask<Void, Void, Bitmap> {
private ImageView imageView;
public ImageLoadTask(ImageView imageView) {
this.imageView = imageView;
}
#Override
protected Bitmap doInBackground(Void... params) {
// download image from server and return
}
#Override
protected void onPostExecute(Bitmap result) {
super.onPostExecute(result);
imageView.setImageBitmap(result)
notifyDataSetChanged()
}
}
and in my getView() method I have:
if(image exists in cache){
myImageView.setBitmap(image in Cache);
}else{
new ImageLoadTask(myImageView).execute()
}
So any images that were stored in the Cache work fine.
Any images that have to be downloaded first will not update correctly, unless you scroll down and back up again.
What is the problem?
I believe you are doing thigs which have been already done and are working rly fine.
I advise you to use library for loading images with listview. One of these is picasso Picasso Android library. This library provides downloading and caching, and can easily (with one line) display them to imageview. Also it provides possibility for placeholder image.
Picasso.with(context)
.load(url)
.resize(50, 50)
.centerCrop()
.into(imageView)
Here is another question on stackoveflow:
Using Picasso library with ListView
EDIT:
If you use picasso you will ALSO solve problem with images wrong displaying while scrolling. This happens if you are loading/downloading them in AsyncTask and you are not doing it correctly.
I was answering question about this problem few daays ago: Why are wrong images getting loaded in ListView occasionally?
Firstly, if you are using the ImageView object directly, then you don't need to call notifyDataSetChanged.
Secondly, what you need to ensure is that the ImageView object you are passing still exists for the same URL requested, i.e., as you must know that Android will re-use views and might be if in between you had scrolled the ImageView object for which you had requested for an URL would have changed to some other URL.
I have worked on a very similar scenario, where I had a separate design like Adapter -> ImageViewRequest(This class will be used to post request, and this class maintains a map of ImageView and URL. So for every request entry is done to the map, and for every response we check that the response for the URL is the current requested URL for the entry of that ImageView and then set accordingly) -> AsyncTask
And also ensure that while setting the bitmap you do that inside a runOnUIThread task to ensure that the image is properly loaded, otherwise you might get a crash saying you are setting in a wrong thread.
Hope that helps :)

Glide caching off screen images in memory

I want to load and cache images only in memory and not pass them to a view and later on when I need them to be loaded on the UI to get them from memory cache if they existed in memory.
I tried:
Glide.with().load(uri).into(new SimpleTarget<GlideDrawable>(WIDTH,HEIGHT)
{
#Override
public void onResourceReady(GlideDrawable resource, GlideAnimation<? super GlideDrawable> glideAnimation) {
//left empty
}
}
);
But when later on I make the call to load that uri in an ImageView it will still load it from the path and not memory.
Is there another way to have images cached in memory without loading them on the UI?
Documentation on how to cache images on background thread can be found here.
Here is some example code from the page showing how a file would be downloaded to cache, without displaying the image in the UI:
FutureTarget<File> future = Glide.with(applicationContext)
.load(yourUrl)
.downloadOnly(500, 500);
// Can be omitted if you only want to have the data cached (same goes for the "future" instance variable
File cacheFile = future.get();
However, make sure you have configured Glide such that caching is enabled: https://github.com/bumptech/glide/wiki/Configuration
Actually I found the preload method in API for this exact purpose:
preload API change log

Android ViewPager: downloading the images from URL

I'm trying to create a image Gallery using ViewPager. I've found several examples and I've got them all to work. The one thing the examples don't show, is how to populate the ViewPager using downloaded images from an URL. All the tutorials either have the images in the Drawables folder or on the SD card. Does anyone know of an example where a ViewPager gets the images from a URL. I've found examples of Lazy Loading a GridView and a ListView, but I'm not smart enough to be able to convert those into a working ViewPager. I mainly run into issues with the Adapter classes. The Lazy Loading examples seem to use BaseAdapter and I think a ViewPager needs to use PagerAdapter right? So, are there any examples of a ViewPager that gets the images from a URL? What I need the ViewPager to do is to download the images from a String Array something like this:
String[] imageGalleryStr = {
"http://www.website.com/images/image01.png",
"http://www.website.com/images/image02.png",
"http://www.website.com/images/image03.png",
"http://www.website.com/images/image04.png",
"http://www.website.com/images/image25.png",
"http://www.website.com/images/image26.png",
"http://www.website.com/images/image27.png",
"http://www.website.com/images/image28.png" };
Any ideas?
use this library for image galary https://github.com/nostra13/Android-Universal-Image-Loader
I haven't tried this code but hopefully something like this should work for you. :)
#Override
public Object instantiateItem(final ViewGroup container, final int position) {
tagShown = false;
View view = ((LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE)).inflate(R.layout.image_view_item, container, false);
imageView = (ImageView) view.findViewById(R.id.imageView);
new DownloadImageInBackground(imageView).execute(imageGalleryStr[position]);
((ViewPager) container).addView(view);
return view;
}
...
private class DownloadImageInBackground extends AsyncTask<String, Void, Bitmap>{
ImageView iv;
public DownloadImageInBackground(ImageView iv) {
this.iv = iv;
}
#Override
protected Bitmap doInBackground(String... params) {
// download bitmap from string url
return bitmap;
}
#Override
protected void onPostExecute(Bitmap result) {
super.onPostExecute(result);
iv.setImageBitmap(result);
}
}
I would recommend you use the Volley library, the same library used by Google in its application Google Play. Please check this answer: Getting Bitmap images from server to set on ImageView
If you already have a working template (ViewPager) maybe you could choose one of the libs for getting images/bitmaps from across the net and then wrap a loader for images inside the Fragment type being operated on by the ViewPager...
When the pager calls 'onCreateView' on the type being paged, you have something like:
imgLoadr.DisplayImage(mMap.get("pic"), imgView);
Your implementation of 'DisplayImage' is built on one of the many libs for networked image management and includes the following details:
DisplayImage implementation looks first for a properly scaled bitmap in memory...
then it looks for a bitmap in local file system cache...
then it fetches the file from across the network and feeds the network stream to get instances of local bitmap/caches.
Your post only concerned the last item above, but IMO you may have to become interest in all of the list because that is just part of working with an image-centric app..
If you are going to be dealing with large album of photos, you probably will have to look at efficiently managing each bitmap and scaling the bitmaps in some way to cut your requirements for memory.

What's LazyList?

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.

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.

Categories

Resources