So at certain times I need to clear the Picasso cache within my application, however when I clear it, the image is the same. If the image URL changes, then it pulls the new image but if the image url is the same, then the old image remains.
Can anyone help me clear the cache so that the image is removed?
This is how I set Picasso up:
Cache picassoCache = new LruCache(MEMORY_CACHE_SIZE);
picassoCacheClearer = new PicassoCacheClearerImpl(picassoCache);
picasso = new Picasso.Builder(context)
.downloader(new OkHttpDownloader(context.getCacheDir(), IMAGE_CACHE_SIZE))
.memoryCache(picassoCache)
.build();
and then try and clear it by:
cache.clear();
Below is the code which actually loads the image:
picasso.load(carouselAction.getImageUrl())
.placeholder(R.drawable.ic_placeholder)
.into(viewHolder.plistImageView);
I can see that the Invalidate() method is now deprecated, so what else can i do?
I have had this same problem and I used this hacky method to get around it. To force it to refresh i would just change the url adding a version tag to it. This is used commonly in web development to make sure things aren't used from the cache.
For example i would load an image from example.com/mypic.png?version=1234
and since the url is different it wouldn't load it from cache.
String versionTag = "?version=" + new Date().getTime();
picasso.load(carouselAction.getImageUrl() + versionTag)
.placeholder(R.drawable.ic_placeholder)
.into(viewHolder.plistImageView);
So found out what the issue was. Turns out for this carousel it was using a different instance of Picasso.
I also had to extend OkHttpDownloader to expose the getClient() method in order to get the cache to delete.
I realised it was a different instance of Picasso by enabling the indicators which can be done by setting the following in the builder
.indicatorsEnabled(true);
Related
I have the same url for an image. When I update this image more than one time it shows the previous image. The image and picture version on the server is updated but Glide is not showing the new image.I want to get new image every time and cache it .
Glide.with(context)
.load(Constants.COPY_LINK_BASE_URL + info.getDisplayPicture())
.placeholder(R.drawable.ic_profile).dontAnimate()
.diskCacheStrategy(DiskCacheStrategy.SOURCE)
.signature(new (SettingManager.getUserPictureVersion(context)))
.into(ivUserProfilePhoto);
I can reproduce this bug by changing internet ,on one internet its change image as expected on other internet it remain same after 2 or 3 tries to changing image
//Use bellow code, it work for me.Set skip Memory Cache to true. it will load the image every time.
Glide.with(Activity.this)
.load(theImagePath)
.diskCacheStrategy(DiskCacheStrategy.NONE)
.skipMemoryCache(true)
.into(myImageViewPhoto);
Glide 4.x
Glide.with(context)
.load(imageUrl)
.apply(RequestOptions.skipMemoryCacheOf(true))
.apply(RequestOptions.diskCacheStrategyOf(DiskCacheStrategy.NONE))
.into(imageView);
Glide 3.x
Glide.with(context)
.load(imageUrl)
.skipMemoryCache(true)
.diskCacheStrategy(DiskCacheStrategy.NONE)
.into(imageView);
TL;DR.
you can skip caching by adding the following lines:
GLIDE v4
Glide.with(context)
.load(url)
.apply(RequestOptions.diskCacheStrategyOf(DiskCacheStrategy.NONE))
.apply(RequestOptions.skipMemoryCacheOf(true))
.into(imageView);
GLIDE v3
Glide.with(context)
.load(url)
.diskCacheStrategy(DiskCacheStrategy.NONE)
.skipMemoryCache(true)
.into(imageView);
OR : you can workaround caching by adding a dummy random argument to your URL:
Glide.with(context)
.load(url + "?rand=" + (new Random().nextInt()))
.into(imageView);
What's happening?
When your picture is loaded the first time, it's stored locally in what's called a cached memory (or simply "a cache"). When you request it for a second time Glide fetches if from the cache as if it was a successful request. This is meant for many good reasons such as: offloading your server, saving your users some data and responding quickly (offering your users a smooth experience).
What to do?
Now, concerning your issue: you need to disable the cache in order to force Glide to fetch your image remotely every time you ask for it. You can do the following:
Glide.with(context)
.load(url)
.diskCacheStrategy(DiskCacheStrategy.NONE)
.skipMemoryCache(true)
.signature(imageVersion) // supposing that each new image has its own version number
.into(imageView);
Or, in the case where you can't know when a picture is changes (no imageVersion), use a unique signature for each picture.
Glide.with(context)
.load(url)
.signature(new StringSignature(String.valueOf(System.currentTimeMillis())))
.into(imageView);
Another clean way would be to configure your picture's cache strategy in your server and use .diskCacheStrategy(DiskCacheStrategy.SOURCE).
A hacky trick worth mentioning
If adding a dummy GET paramter to your target URL doesn't break anything, then you could simply workaround caching by passing a random argument each time you fetch the image, this will push Glide to think you're querying a new endpoint, since the image cannot possibly exist in the cache.
Glide.with(context)
.load(url + "?rand=" + (new Random().nextInt())) // "&rand=" if your url already has some GET params
.into(imageView);
Glide caching API here.
I my case Glide not recognize .signature(), so additionally to #MGDavies's answer you maybe need something like this
// in kotlin
Glide.with(context)
.load("url")
//using apply to RequestOptions instead signature directly
.apply(RequestOptions().signature(ObjectKey("time that image was updated")))
.into(thumb)
This is an old question, so I'm sure you've got your fix by now. However I believe both of the big libraries(Picasso and Glide) now support something similar.
Glide has its signature API you may wish to look into:
https://github.com/bumptech/glide/wiki/Caching-and-Cache-Invalidation
Glide.with(yourFragment)
.load(yourFileDataModel)
.signature(new StringSignature(yourVersionMetadata))
.into(yourImageView);
I've not had a chance to work with this myself, but it looks as though you need to make a call to your API to get the version Metadata, then a subsequent call to fulfil it.
Alternatively, look into ETags.
Good luck!
Glide 4.8.0
Glide.with(mContext).asBitmap()
.load(nopicUrl)
.apply(RequestOptions.skipMemoryCacheOf(true))
.apply(RequestOptions.signatureOf(new ObjectKey(String.valueOf(System.currentTimeMillis()))))
.apply(RequestOptions.diskCacheStrategyOf(DiskCacheStrategy.DATA))
.into(ivImageView);
Now Glide latest version, you have to use RequestOption for clear cache.
RequestOptions options = new RequestOptions()
.diskCacheStrategy(DiskCacheStrategy.NONE)
.skipMemoryCache(true);
Or for everytime load picture you have to use a String in as signature.
RequestOptions options = new RequestOptions()
.signature(new StringSignature(String.valueOf(System.currentTimeMillis())));
Finally:
Glide.with(CompressSingleActivity.this)
.applyDefaultRequestOptions(options)
.load(currentFile)
.into(currentImageView);
When new images are loaded or updated, use below to clear Glide memory and cache :
|==| Clear Glide memory
Glide.get(getApplicationContext()).clearMemory();
|==| Clear Glide Cache()
void clearGlideDiskCache()
{
new Thread(new Runnable()
{
#Override
public void run()
{
Glide.get(getApplicationContext()).clearDiskCache();
}
}).start();
}
diskCacheStrategy and skipMemoryCache did not work for my case.
I was writing to a local image file between Glide requests with the same url. My hack of a solution was to switch between adding a 0/1 to the end of the filename.
Forcing it to change image source every time seems to work.
Try using RequestOptions:
RequestOptions requestOptions = new RequestOptions();
requestOptions.placeholder(R.drawable.ic_placeholder);
requestOptions.error(R.drawable.ic_error);
Glide.with(context)
.setDefaultRequestOptions(requestOptions)
.load(url).into(holder.imageView);
If .setDefaultRequestOptions(requestOptions) does not work, use .apply(requestOptions):
Glide.with(MainActivity.this)
.load(url)
.apply(requestOptions)
.into(imageview);
// or this
Glide.with(MainActivity.this)
.load(url)
.apply(new RequestOptions().placeholder(R.drawable.booked_circle).error(R.drawable.booked_circle))
.into(imageview);
// or this
Glide.with(MainActivity.this)
.load(url)
.apply(RequestOptions.placeholderOf(R.drawable.booked_circle).error(R.drawable.))
.into(imageview);
it's like the issue is related to Glide Library itself, I found the trick that can fix this, just put a random number after your image URL as a query like an Example code below, it fixed my problem I hope it helps you too
Random random = new Random();
int randomInt = random.nextInt();
Glide.with(context)
.applyDefaultRequestOptions(new RequestOptions()
.circleCrop().diskCacheStrategy(DiskCacheStrategy.NONE))
.load(ConstantVars.BaseUrl + userModel.getAvatarURL() + "?" + randomInt)
.apply(new RequestOptions().error(R.drawable.himart_place_holder))
.into(imageViewProfile);
it will make Glide to reload image anytime you request like there's no cache at all to read from.
I am building my application using Android Studio, this app can upload an image from raspberry to my emulator. It works fine. What I want to do now is uploading this image and showing it directly to the user without searching it in the gallery. I thought about creating another class and setting this image as a background image in my xml file, but this is too much like I have to create another class every time I want to upload an image from my raspberry.
Can someone help me please. Thank you
If I'm understanding your question correctly, you'd like to load an image from the Android filesystem into your app and display it to the user.
Drawable, Android's generalized image class, allows you to load from file via Drawable#createFromPath.
This SO question suggests Drawable#createFromPath doesn't work on paths beginning with file://, so depending on your use case you may want to precede that with Uri#parse/Uri#getPath.
Once you have a Drawable, you can display it in one of two ways: put an ImageView in your app and call its setImageDrawable method, or set the Drawable as your background image via View#setBackground (note that setBackground was only added in API 16 - in prior versions, you should call View#setBackgroundDrawable).
Putting all of this together, we end up with the following (untested):
private void loadImage(String imagePath) {
Uri imageUri;
String fullImagePath;
Drawable image;
ImageView imageDisplay;
imageUri = Uri.parse(imagePath);
fullImagePath = imageUri.getPath();
image = Drawable.createFromPath(fullImagePath);
imageDisplay = (ImageView) findViewById(R.id.imageDisplay);
/*if image is null after Drawable.createFromPath, this will simply
clear the ImageView's background */
imageDisplay.setImageDrawable(image);
/*if you want the image in the background instead of the foreground,
comment the line above and uncomment this bit instead */
//imageDisplay.setBackground(image);
}
You should be able to modify this to work with any View just by replacing imageDisplay's declared type with the appropriate View type and changing the cast on findViewById. Just make sure you're calling setBackground, not setImageDrawable, for a non-ImageView View.
I'm making this netflix style app in which images are loaded into different categories. Let's say Dog videos (has 15 images), Cat videos (15 images), etc... All the images are loaded from a URL, it kind of takes a while for all to load. I was wondering if there was anything I could do to speed up the process? Or maybe show an empty container then fill it as the images load (that would be cool).
This is what I have done:
I have multiple async calls in one Activity, (1 async call per category)
JSONTask1 dogTask = new JSONTask1();
JSONTask2 catTask = new JSONTask2();
JSONTask3 pigTask = new JSONTask3();
JSONTask4 horseTask = new JSONTask4();
dogTask.execute("");
catTask.execute("");
pigTask.execute("");
horseTask.execute("");
I have all of those in a row in my actual code. Thanks.
I would use the "proxy pattern". Basically, you need to create a class that contains the minimal informations required for the display. In which, you have a preview image.
When ever you load everything you start by showing the preview content, ie : a loading gif for everypicture with the title of the movie or whatever. and basically the proxy would have a "loadImage" method that would make an ajax call or async call and the photos would load one by one. Plus, to make the loading easier, make sure the photos are not oversized.
You can see Picasso answers , in picasso i suggest you this way :
Picasso.with(getApplicationContext()).load("your url").placeholder(R.drawable.your_place_holder).error(R.drawable.showing_when_error_occured)
.into(imageView, new Callback() {
#Override
public void onSuccess() {
}
#Override
public void onError() {
}
});
Also another suggestion from me : convert your thumb images to base64 format in backend, then firstly retrieve your thumbs and show them. Then start an async task and change images when successfull.
Like whatsapp. In whatsapp you have thumb images they have so low resolution and super fast. When you click image if you have internet connection they load actual thumb images, and click again they load larger image.
Picasso website :http://square.github.io/picasso/
Load them asynchronously with Picasso, you can even show a placeholder image until the real one is loaded
I am developing an android app.In that app, the server stores the images that is to be displayed in imageView of listview. I use picasso to get image from the server and display in imageview. Though I had uploaded new images in server, only old images are being displayed again. I suspect this is due to cache in picasso.
I used 3 methods to prevent cache:
Picasso.with(getActivity()).load(data.get(pos).getFeed_thumb_image()).skipMemoryCache().into(image);
Picasso.with(getActivity()).load(data.get(pos).getFeed_thumb_image()).memoryPolicy(MemoryPolicy.NO_CACHE).into(image);
Picasso.with(context).invalidate(imagePath);
But in no result. How can I clear cache in picasso for particular url?
This is going to be implemented in the future, but see the post of Jake Wharton:
JakeWharton commented on 11 Dec 2014 Current best candidate:
picasso.load('http://example.com/')
.cachePolicy(NO_CACHE, NO_STORE)
.networkPolicy(NO_CACHE, NO_STORE, OFFLINE)
.into(imageView);
enum MemoryPolicy {
NO_CACHE, NO_STORE
}
enum NetworkPolicy {
NO_CACHE, NO_STORE, OFFLINE
}
This will be what's implemented unless anyone has other thoughts.
Try load url with variable like time now:
Calendar urlvar = Calendar.getInstance();
int seconds = urlvar.get(Calendar.SECOND);
Then load your url by adding to string: ?urlvar so the final loaded url will be for example example.com/m.png?date it will be cashed but next load the date is changed so the url will change so will not load from cash. Hope ot work
In my Android app I use Picasso to load images. This normally works perfectly well.
Today I tried loading a static image from the google maps api, but this doesn't seem to work. When I open the example link as provided on their info page, I get to see the static map image perfectly well. When I load it in my Android app using the line below, I get nothing at all.
Picasso.with(getContext()).load("http://maps.googleapis.com/maps/api/staticmap?center=Brooklyn+Bridge,New+York,NY&zoom=13&size=370x250&maptype=roadmap%20&markers=color:blue|label:S|40.702147,-74.015794&markers=color:green|label:G|40.711614,-74.012318%20&markers=color:red|color:red|label:C|40.718217,-73.998284&sensor=false").into(mapView);
I also tried to download the image and uploading it to my personal webspace, from which it loads perfectly well, but somehow, it doesn't seem to load directly from the direct google API url.
Does anybody know why this is so, and how I can solve it?
The only programmatic point-of-failure that comes to mind is in parsing the URI. Looking at the current Picasso code (https://github.com/square/picasso/blob/master/picasso/src/main/java/com/squareup/picasso/Picasso.java) I see the following:
public RequestCreator load(String path) {
if (path == null) {
return new RequestCreator(this, null, 0);
}
if (path.trim().length() == 0) {
throw new IllegalArgumentException("Path must not be empty.");
}
return load(Uri.parse(path));
}
So I'd first debug
Uri.parse("http://maps.googleapis.com/maps/api/staticmap?center=Brooklyn+Bridge,New+York,NY&zoom=13&size=370x250&maptype=roadmap%20&markers=color:blue|label:S|40.702147,-74.015794&markers=color:green|label:G|40.711614,-74.012318%20&markers=color:red|color:red|label:C|40.718217,-73.998284&sensor=false")
and see what that Object looks like. Does it drop or confuse any of your parameters?
If that doesn't lead you anwhere, try downloading the file manually using a HttpClient [or similar]. Then at least you can fully debug the request/response.
Also, I know Google maps has some limits -- are you sure you haven't reached them?
replace http with https
replace | with %7C
add api key
The .loadMap() function has many declared variables. This is the heart of the whole process.
So what is required for the static maps API to give us an image is that we make an http request with a given url, for which an image response (URL) is received. Let us run through the meaning and utility of these variables. Yes, all of them have a completely different meaning!
The mapUrlInitial variable is always the same while making an API call. It has a query of center ( ?center ) which specifies that we want the location to be centered in the map.
The mapUrlProperties variable contains a string where you control the actual zooming of the image response you will get, the size ofthe image and the color of the marker which will point out our place.
The mapUrlMapType variable is a string where you can actually determine the marker size you want and the type of the map. We are using a roadtype map in the app.
Finally latLong is a string which concatenates the latitude and the longitude of the place we want to pinpoint!
We then concatenate all of these strings to form a feasible Url. The Url is then loaded as we have seen above, in the Picasso code. One thing we can notice is that an event object is always required for all of this to happen, because we are able to fetch the position details using the event object! Final Code:-
fun loadMap(event: Event): String{
//location handling
val mapUrlInitial = “https://maps.googleapis.com/maps/api/staticmap?center=”
val mapUrlProperties = “&zoom=12&size=1200×390&markers=color:red%7C”
val mapUrlMapType = “&markers=size:mid&maptype=roadmap”
val latLong: String = “” +event.latitude + “,” + event.longitude
return mapUrlInitial + latLong + mapUrlProperties + latLong + mapUrlMapType
}
//load image
Picasso.get()
.load(loadMap(event))
.placeholder(R.drawable.ic_map_black_24dp)
.into(rootView.image_map)