Out of Memory issue in a gallery like application - android

I am trying to create an application which contains lots of Images from web services.I am using Picasso library for loading images into a gallery like fragment with RecyclerView having lazy load and passing list of URL's to slider activity with ViewPager i am dealing lot of images so after few slides it starts throwing Out of Memory(OOM) exception.I have tried with Glide its is stretching the image so i stick with Picasso.Tried a lot of methods like using large heap and allowing hardware access.Any method to identify and handle this issue would be helpful.
Picasso.with(context)
.load(image.getImageURL())
.memoryPolicy(MemoryPolicy.NO_CACHE, MemoryPolicy.NO_STORE)
.skipMemoryCache()
.placeholder(R.drawable.poster_default)
.error(R.drawable.poster_default)
.into(mImageView);

Agree with previous answer. You can also try use RGB_565 config. The image with this config two times smaller
Picasso picasso = new Picasso.Builder(this)
.defaultBitmapConfig(Bitmap.Config.RGB_565)
.build();
And set this instance to picasso
Picasso.setSingletonInstance(picasso);
The code snippet should be placed in onCreate method in android.app.Application class

Android uses bitmaps for images so that would mean adding large images will consume tons of memory. What I do in my projects is add fit() to the Picasso call to it so it will resize the image for me instead of loading it full size in memory.
Try something like below and see if it's fixed
Picasso.with(context)
.load(image.getImageURL())
.fit()
.centerCrop()
.memoryPolicy(MemoryPolicy.NO_CACHE, MemoryPolicy.NO_STORE)
.skipMemoryCache()
.placeholder(R.drawable.poster_default)
.error(R.drawable.poster_default)
.into(mImageView);

Related

How to prevent of loading images from previous results?

I am implementing search and there are cases when images of old results are loaded and applyed to new ones, so how can I prevent Glide loading images and displaying on imageView when I have new search results.
If you're using Glide to load images, you can completely skip the caching of images by using something like below:
Glide.with(fragment)
.load(url)
.diskCacheStrategy(DiskCacheStrategy.NONE)
.into(view);

Big images loading with Picasso

I have a list view where I load image with person name. There are around 538 items in the list view. I get the images of persons from a url. Currently I am doing the following:-
Picasso.with(getContext()).load(url).resize(70,70).onlyScaleDown().into(im1);
The images present in the URL are very large in size and loading of some images takes a lot of time and it eats up my memory also while loading. Can some one please help me in loading the images efficiently and fastly.
Example image for one person can be found in the following URL:-
https://theunitedstates.io/images/congress/original/D000626.jpg
You can use onlyScaleDown() to resize
Picasso
.with(context)
.load(imageUrl)
.resize(6000, 2000)
.onlyScaleDown() // the image will only be resized if it's bigger than 6000x2000 pixels.
.into(imageViewResizeScaleDown);
Or you can use fit()
Picasso
.with(context)
.load(imageUrl)
.fit()
// call .centerInside() or .centerCrop() to avoid a stretched image
.into(imageViewFit);
fit() is measuring the dimensions of the target ImageView and internally uses resize() to reduce the image size to the dimensions of the ImageView. There are two things to know about fit(). First, calling fit() can delay the image request since Picasso will need to wait until the size of the ImageView can be measured. Second, you only can use fit() with an ImageView as the target (we'll look at other targets later).
The advantage is that the image is at the lowest possible resolution, without affecting its quality. A lower resolution means less data to be hold in the cache. This can significantly reduce the impact of images in the memory footprint of your app. In summary, if you prefer a lower memory impact over a little faster loading times, fit() is a great tool.
As per the new version of Picasso
Picasso.get().load(galleryList[position].mediaUrl).fit()
.placeholder(R.mipmap.ic_launcher).into(holder?.ivImags)

Glide not loading image from memory at the first time when rotating (orientation change), and after that it is loading from memory

Glide not loading image from memory at the first time when rotating (orientation change), and after that it is loading from memory.
I have tried to increase the memory size, the bitmap pool size, all kinds of caching strategies... nothing seemed to work...
I have attached a video.
https://youtu.be/szDnAGxrJLU
Thanks!
.dontAnimate() adding this to Glide solved my problem
Glide.with(view.getContext())
.load(url)
.placeholder(placeholder_image_crop))
.dontAnimate()
.into(view)
You may face this issue because of
CircleImageView/CircularImageView/RoundedImageView are known to have issues with TransitionDrawable (.crossFade() with .thumbnail() or .placeholder()) and animated GIFs, use a BitmapTransformation (.circleCrop() will be available in v4) or .dontAnimate() to fix the issue.
for more queries refer following links it may help you.
link 1 and link 2
Your ImageViews don't have the exact same size in portrait and in landscape and you are probably using fitCenter() or centerCrop() to resize the image to the ImageView size. When you change orientation, Glide loads the full-sized image from cache but it has to resize it on a background thread first before display, that's why you see a delay after the first orientation change. After resized images for both portrait and landscape are in the memory cache, there is no more delay.
Just to emphasize what is written above and add a solution.
It is possible to change the disk caching strategy to cache the source image but not the memory caching strategy, in that case it will not hit unless it is the same size.
What i did was use .override(width,height) in order to override this strategy and keep the source image in the memory cache.
Glide.with(context)
.load(imgUrl)
.crossFade()
.override(imageWidth,imageHeight)
.into(imgView);
To load image from cache you can pass DiskCacheStrategy.SOURCE to load images from cache.
You can use glide like below and keep don't animate method as it helps to load images in adapter without updating full list. For more check this
Glide.with(context)
.load(row_object.getImage())
.dontAnimate() // will load image
.diskCacheStrategy(DiskCacheStrategy.SOURCE)
.placeholder(ContextCompat.getDrawable(context,
R.mipmap.ic_user_placeholder_50dp))
.into(holder.rowIvPostUserIcon);
This code help me:
Glide.with(view.getContext())
.load(url)
.placeholder(AppCompatResources.getDrawable(view.getContext(), R.drawable.vector_placeholder_vendor_image_crop))
.dontAnimate()
.into(view);
//need add .dontAnimate()
For more information:
https://github.com/bumptech/glide/issues/1026#issuecomment-191709837
First Time glide is unable to load image on custom view like circular Imageview.you Can use error to load image on first time.
The following snippet should help you:
Glide.with(context)
.load(imgUrl)
.crossFade()
.override(imageWidth,imageHeight).error(R.drawable.yourdrawable)
.into(imgView);

Loading Same Gallery Image Into Two Different Activity Fragments Android Picasso

Currently I have a Main Activity which has a Fragment loaded into it with a RecyclerView. In the RecyclerView adapter I use Picasso to load in images from the user's gallery based on a stored URI string I have like so:
Picasso.with(context)
.load(imageUri)
.resize(400, 400)
.into(viewHolder.imageView);
When the user clicks on one of these items in the RecyclerView I go to a new Activity and inside its own Fragment onCreateView I load the same image again but size it slightly larger (as the ImageView I'm loading it into is larger size)
Picasso.with(getActivity())
.load(imageUri)
.resize(600, 600)
.centerCrop()
.into(imageView);
My question is...Assuming these images can be quite large...
Is there a better way to load in this image once at say 600px X 600px back when the RecyclerView first needs them, and then reuse the bitmap data in the subsequent Activities and Fragments which need it without reloading again?
I'm open to using a different image loader like Volley if that's better.
Any help would be appreciated.
Marco
You could try Glide it has almost the same api. Instead of Picasso glide has own cache implementation, when Picasso just use http cache and it's hard to control. In glide you need to specify diskCacheStrategy.ALL to make glide cache all you want. Here is cache wiki

Does Picasso apply resize options during fetch()?

I am referring to this post Getting Picasso to pre-fetch forthcoming images where #BillMote uses fetch() with centerCrop() and further options:
Picasso.with(getApplicationContext())
.load(url)
.resizeDimen(R.dimen.article_image_preview_width, R.dimen.article_image_preview_height)
.centerCrop()
.fetch();
Will Picasso honor such options at all, or will Picasso save the image straight to the cache so these options are ignored and should be used later when the image is pulled from the cache and viewed?
It still isn't clear to me (and after 6 months I haven't found any documentation where this was clearly defined [I admit I haven't investigated into this either]) if Picasso applies any such options before saving the file to the cache, or repeatedly every time it displays an image.
Something like centerCrop() makes no sense to me in above statement, because the size of the target ImageView isn't clear at this point. This might be different for resizeDimen(), but I stil doubt Picasso will apply the dimensions because JakeWharton once said in a post that Picasso relies on okhttp for image caching.
Can anybody shed light please.

Categories

Resources