Small unwanted delay loading icons with Glide - android

I've a list of installed applications that I display in a RecyclerView.
The application icon is stored in a byte array and I use Glide to bind it to an ImageView using:
Glide.with(itemView.getContext())
.load(application.getIcon())
.into(icon);
The problem is that it tooks about 500-700 ms for the icon to be displayed, then it appears in a nice and smooth way. But I don't want that delay nor want to fallback to a placeholder.
If I change Glide code for direct loading (in main application thread) then the icons appear instantly:
byte[] image = application.getIcon();
BitmapFactory.Options options = new BitmapFactory.Options();
options.inPreferredConfig = Bitmap.Config.ARGB_8888;
Bitmap bitmap = BitmapFactory.decodeByteArray(image,0,image.length,options);
icon.setImageBitmap(bitmap);
But the problem is that If I scroll fast the list sometimes there are some little glitches.
Is there something that I can do to load the icons faster with Glide?
I've tried with .dontAnimate() and .dontTransform() but I haven't seen any differences. What can I do to load the images instantly and get similar results than loading directly in main thread?

Related

How to display images from URL efficently

I need to display a list of images in my application, and i get those images from an API call as an URL. Now I'm using Glide to show them, but i don't like the loading effect it makes (blank space while loading, and the the image). Is there any way to instant show those images, without any loading time and possibly without downloading them?
Since the images are stored on a remote server there is no way to bypass the downloading process, however Glide makes sure to only download the image from remote server when necessary, as the docs state
By default, Glide checks multiple layers of caches before starting a
new request for an image:
Active resources - Is this image displayed in another View right now?
Memory cache - Was this image recently loaded and still in memory?
Resource - Has this image been decoded, transformed, and written to
the disk cache before? Data - Was the data this image was obtained
from written to the disk cache before? The first two steps check to
see if the resource is in memory and if so, return the image
immediately. The second two steps check to see if the image is on disk
and return quickly, but asynchronously.
If all four steps fail to find the image, then Glide will go back to
the original source to retrieve the data (the original File, Uri, Url
etc).
To resolve this,
but i don't like the loading effect it makes (blank space while
loading, and the the image)
You can instead add a default placeholder on the ImageView until the real image is downloaded. This will display a default image while your actual image is downloading and then after download completion will replace it with the actual one.
Glide
.with(context)
.load(url)
.placeholder(R.drawable.ic_placeholder) //your default placeholder resource
.into(imageView)
you can display images from url by two ways:
Without any third party library:
URL url = new URL("URL of image here");
Bitmap bitmap = BitmapFactory.decodeStream(url.openConnection().getInputStream());
imageView.setImageBitmap(bitmap);
Second way is by using Picasso

UIL, Picasso - Images in adapter always reload when stop scrolling

I have ListView with text and large image from internet. My image item has fit width and wrap_content height.
I tried to display image in background with UIL & Picasso. Both of them can work but the image always reloads when I stop scrolling, and it makes ListView flickering
It looks like this:
You can see that it reload downloaded and cached images when I stop scrolling (I scroll down and then scroll up).
How can I prevent this happen?
<ImageView android:id="#+id/imgFeed"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:scaleType="centerCrop"/>
// UIL
options = new DisplayImageOptions.Builder()
.showImageOnLoading(defaultImage)
.showImageOnFail(defaultImage)
.showImageForEmptyUri(defaultImage)
.resetViewBeforeLoading(false)
.cacheOnDisk(true).delayBeforeLoading(0)
.displayer(new FadeInBitmapDisplayer(200)).cacheInMemory(true).imageScaleType(ImageScaleType.EXACTLY_STRETCHED).build();
ImageAware imageAware = new ImageViewAware(viewHolder.imgFeed, false);
ImageLoader.getInstance().displayImage(item.getPhotoUrl(), imageAware, options);
// Picasso
Picasso.with(getContext())
.load(item.getPhotoUrl())
.placeholder(R.drawable.place_holder_big)
.resize(screenWidth, 0) //set max width
.into(viewHolder.imgFeed);
For UIL, I tried many ways in this issue but they don't work for me at all.
Update: seems I faced with memory cache issue like this question. But how can I fix this issue? Look at Facebook app, they did it very well. All images have different sizes with fit width, and very smooth scrolling without reloading images. How can they do that?
If you're wondering how Facebook did it, they actually released their image loading library (https://github.com/facebook/fresco)
Is it possible you are actually calling notifyDataSetChanged on the underlying ListView at that time? Also are you using hasStableIds()?
For UIL you could try using a WeakMemoryCache (refer to https://github.com/nostra13/Android-Universal-Image-Loader/wiki/Useful-Info) as that'll theoretically allow you to make use of all available memory though it may cause a lot of extra GC calls.
For Picasso Taha's method looks like your best bet!
Maybe your memory cache size is small and Picasso tries to load images from disc cache. Please check here for deciding cache size. You can try to increase cache size of Picasso by:
Picasso p = new Picasso.Builder(context)
.memoryCache(new LruCache(cacheSize))
.build();
However in my opinion your app looks like having an endless feed. Which means your memory cache will be full at some time and you'll have to use disc cache. Retrieving data from the disc cache is slower compared to memory cache.

Load bitmap lazy, just before it is seen

I've a Listview with images. I am using an adapter to display the images because i get just a URL from a web service. At the moment i load all images Async, that works but its very inefficient. I get 100-200 images / URLs and mostly i do not need all.
I am looking for a solution to load a bitmap just before it is seen.
for example:
Bitmap 1 (i see it on the screen -> load bitmap)
Bitmap 2 (i see it on the screen -> load bitmap)
Bitmap 3 (i don't see it on the screen but its the next one -> load bitmap)
Bitmap 4 (i don't see it, nothing to do)
Bitmap 5 (i don't see it, nothing to do)
How can I do this?
You should implement the Holder pattern for your listview. See the documentation here
I use Universal Image Loader library, and lazy loading works perfect, take a look at it here:
Universal Image Loader at Github

Animation with large number of bitmaps

I've seen similar threads here but couldn't find a sufficient solution yet.
I'm working on my first Android app and trying to create an animation using large amount of images/bitmaps. I have a list of bitmaps which I like to play frame-by-frame animation
the number of images may change from few to hundreds (currently loaded from resources)
I'm using SurfaceView and using the following to load and draw my images
Bitmap bitmap = BitmapFactory.decodeResource(getResources(), res);
canvas.drawBitmap(bitmap, x, y, null);
I tried two methods:
Pre-Loading all images and caching to memory. This results with great performance
but takes time to initialize, uses a lot of memory and works only for small amount of images
Decoding the images one-by-one. This results with poor performance and high cpu usage
I'm looking for way to boost the performance for large lists,
Is there a way to cache the decoded bitmaps or convert them to some video-stream (lossless?) to boost performance?
Any ideas?
About performance,
First do not load the hole image size, use below method to reduce size when load image:
BitmapFactory.Options options = new BitmapFactory.Options();
options.inSampleSize = number; //reduce image size
Bitmap b = BitmapFactory.decodeFile(image path, options);
Also load images for current time animation not all animations, then load other animations in thread instead of finished animation.
About time in case 2, load images in a thread and show loading dialog for the user until all images loaded.

ListView with photos from Gallery

I have a listview that has a photograph from the gallery for each entry but it was blowing up and running out of memory so I resized the image
BitmapFactory.Options opts = new BitmapFactory.Options();
opts.inSampleSize = 8;
Bitmap yourSelectedImage = BitmapFactory.decodeFile(photo,opts);
imgView.setImageBitmap(yourSelectedImage);
The problem I have is that each image in the list has to be resized before it is displaying the view.
Is there a way to link to the thumbnail view instead of the full size image so that I don't have to resize them or is there a way to load each picture as it is sized instead of having to wait for them all.
This basically sounds like exactly the sort of thing you want from droid-fu's remote image handling, only simpler (the "remote loading" part is really just scaling an image loaded from the Gallery instead of downloading one from the Web). You should be able to use very similar code. Alternatively, this is pretty close to this SO question about lazy-loading images.

Categories

Resources