I use Glide library for Android. I want to set the cache in my custom folder, so the standard cache folder can be clean (with Master Clean for example).
For this reason I use this code from manual, but this don't work for me.
My code:
DiskCache.Factory diskCacheFactory = new DiskCache.Factory() {
#Override
public DiskCache build() {
DiskCache diskCache = DiskLruCacheWrapper.get(getFilesDir(), 1024*1024*100);
return diskCache;
}
};
new GlideBuilder(this).setDiskCache(diskCacheFactory);
Glide.with(this)
.load("http://www.website.com/1.jpg")
.into(imageView);
After I run this app Glide saves the image in the default folder.
In Glide 3.5, Glide.isSetup() and Glide.setup() are deprecated. The best way to do this is to use GlideModules to do this kind of configuration lazily. Check out the wiki page on configuration.
Try use:
if (!Glide.isSetup()) {
GlideBuilder gb = new GlideBuilder(this);
DiskCache dlw = DiskLruCacheWrapper.get(new File(Environment.getExternalStorageDirectory().getAbsolutePath() + "/myCatch/"), 250 * 1024 * 1024);
gb.setDiskCache(dlw);
Glide.setup(gb);
}
Related
I want to cache all images without displaying them so that the image will be displayed even if there isn't any available network
Is it possible with Fresco Image Loader?
Yes, you can, see their cache page for details.
To configure the cache you should do something like:
DiskCacheConfig diskCacheConfig = DiskCacheConfig.newBuilder()
.set....
.set....
.build()
// when building ImagePipelineConfig
.setMainDiskCacheConfig(diskCacheConfig)
Then to check if it persisted in the local storage cache, you can use:
DataSource<Boolean> inDiskCacheSource = imagePipeline.isInDiskCache(uri);
DataSubscriber<Boolean> subscriber = new BaseDataSubscriber<Boolean>() {
#Override
protected void onNewResultImpl(DataSource<Boolean> dataSource) {
if (!dataSource.isFinished()) {
return;
}
boolean isInCache = dataSource.getResult();
// your code here
}
};
inDiskCacheSource.subscribe(subscriber, executor);
To prefetch the images you can use something like:
final PrefetchSubscriber subscriber = new PrefetchSubscriber();
for (Uri uri : mUris) {
final DataSource<Void> ds = Fresco.getImagePipeline().prefetchToDiskCache(ImageRequest.fromUri(uri), null);
ds.subscribe(subscriber, UiThreadImmediateExecutorService.getInstance());
}
See here their full sample for more details.
I am currently using Picasso to download and cache images in my app inside multiple recycler views. So far Picasso has used around 49MB cache size and i am worried that as more images come into play, this will become much higher.
I am using the default Picasso.with(context) object. Please answer the following:
1) Is there a way to restrict the Size of Picasso's cache. MemoryPolicy and NetworkPolicy set to NO_CACHE isn't an option. I need caching but upto a certain level (60MB max)
2) Is there a way in picasso to store Resized/cropped images like in Glide DiskCacheStrategy.RESULT
3) If the option is to use OKHTTP, please guide me to a good tutorial for using it to limit Picasso's cache size. (Picasso 2.5.2)
4) Since i am using a Gradle dependency of Picasso, how can i add a clear Cache function as shown here:
Clear Cache memory of Picasso
Please try this one, it does seem to work great for me:
I use it as a Singleton.
Just put 60 where DISK/CACHE size parameters are.
//Singleton Class for Picasso Downloading, Caching and Displaying Images Library
public class PicassoSingleton {
private static Picasso mInstance;
private static long mDiskCacheSize = CommonConsts.DISK_CACHE_SIZE * 1024 * 1024; //Disk Cache
private static int mMemoryCacheSize = CommonConsts.MEMORY_CACHE_SIZE * 1024 * 1024; //Memory Cache
private static OkHttpClient mOkHttpClient; //OK Http Client for downloading
private static Cache diskCache;
private static LruCache lruCache;
public static Picasso getSharedInstance(Context context) {
if (mInstance == null && context != null) {
//Create disk cache folder if does not exist
File cache = new File(context.getApplicationContext().getCacheDir(), "picasso_cache");
if (!cache.exists())
cache.mkdirs();
diskCache = new Cache(cache, mDiskCacheSize);
lruCache = new LruCache(mMemoryCacheSize);
//Create OK Http Client with retry enabled, timeout and disk cache
mOkHttpClient = new OkHttpClient();
mOkHttpClient.setConnectTimeout(CommonConsts.SECONDS_TO_OK_HTTP_TIME_OUT, TimeUnit.SECONDS);
mOkHttpClient.setRetryOnConnectionFailure(true);
mOkHttpClient.setCache(diskCache);
//For better performence in Memory use set memoryCache(Cache.NONE) in this builder (If needed)
mInstance = new Picasso.Builder(context).memoryCache(lruCache).
downloader(new OkHttpDownloader(mOkHttpClient)).
indicatorsEnabled(CommonConsts.SHOW_PICASSO_INDICATORS).build();
}
}
return mInstance;
}
public static void updatePicassoInstance() {
mInstance = null;
}
public static void clearCache() {
if(lruCache != null) {
lruCache.clear();
}
try {
if(diskCache != null) {
diskCache.evictAll();
}
} catch (IOException e) {
e.printStackTrace();
}
lruCache = null;
diskCache = null;
}
}
1) Yeah, easy: new com.squareup.picasso.LruCache(60 * 1024 * 1024). (just use your Cache instance in your Picasso instance like new Picasso.Builder(application).memoryCache(cache).build())
2) Picasso automatically uses the resize() and other methods' parameters as part of the keys for the memory cache. As for the disk cache, nope, Picasso does not touch your disk cache. The disk cache is the responsibility of the HTTP client (like OkHttp).
3) If you are talking about disk cache size: new OkHttpClient.Builder().cache(new Cache(directory, maxSize)).build(). (now you have something like new Picasso.Builder(application).memoryCache(cache).downloader(new OkHttp3Downloader(client)).build())
4) Picasso's Cache interface has a clear() method (and LruCache implements it, of course).
Ok, I did a lot of digging inside Picasso, and OKHTTP's internal working to find out how caching happens, whats the policy etc.
For people trying to use latest picasso 2.5+ and Okhttp 3+, the accepted answer WILL NOT WORK!! (My bad for not checking with the latest :( )
1) The getSharedInstance was not Thread safe, made it synchronized.
2) If you don't to do this calling everytime, do a Picasso.setSingletonInstance(thecustompicassocreatedbygetsharedinstance)
P.S. do this inside a try block so as to avoid illegalstateexception on activity reopening very quickly after a destroy that the static singleton is not destroyed. Also make sure this method gets called before any Picasso.with(context) calls
3) Looking at the code, I would advise people not to meddle with LruCache unless absolutely sure, It can very easily lead to either waste of unused RAM or if set low-> Outofmemoryexceptions.
4)It is fine if you don't even do any of this. Picasso by default tries to make a disk cache from it's inbuilt okhttpdownloader. But this might or might not work based on what picasso version you use. If it doesn't work, it uses default java URL downloader which also does some caching of its own.
5) Only main reason i see to do all this is to get the Clear Cache functionality. As we all know Picasso does not give this easily as it is protected inside the package. And most mere mortals like me use gradle to include the package leaving us out in the dust to not have cache clearing access.
Here is the code along with all the options for what i wanted. This will use Picasso 2.5.2 , Okhttp 3.4.0 and OkHttp3Downloader by jakewharton.
package com.example.project.recommendedapp;
import android.content.Context;
import android.util.Log;
import com.jakewharton.picasso.OkHttp3Downloader;
import com.squareup.picasso.LruCache;
import com.squareup.picasso.Picasso;
import java.io.File;
import java.io.IOException;
import java.util.concurrent.TimeUnit;
import okhttp3.Cache;
import okhttp3.OkHttpClient;
//Singleton Class for Picasso Downloading, Caching and Displaying Images Library
public class PicassoSingleton {
private static Picasso mInstance;
private static long mDiskCacheSize = 50*1024*1024; //Disk Cache limit 50mb
//private static int mMemoryCacheSize = 50*1024*1024; //Memory Cache 50mb, not currently using this. Using default implementation
private static OkHttpClient mOkHttp3Client; //OK Http Client for downloading
private static OkHttp3Downloader okHttp3Downloader;
private static Cache diskCache;
private static LruCache lruCache;//not using it currently
public static synchronized Picasso getSharedInstance(Context context)
{
if(mInstance == null) {
if (context != null) {
//Create disk cache folder if does not exist
File cache = new File(context.getApplicationContext().getCacheDir(), "picasso_cache");
if (!cache.exists()) {
cache.mkdirs();
}
diskCache = new Cache(cache, mDiskCacheSize);
//lruCache = new LruCache(mMemoryCacheSize);//not going to be using it, using default memory cache currently
lruCache = new LruCache(context); // This is the default lrucache for picasso-> calculates and sets memory cache by itself
//Create OK Http Client with retry enabled, timeout and disk cache
mOkHttp3Client = new OkHttpClient.Builder().cache(diskCache).connectTimeout(6000, TimeUnit.SECONDS).build(); //100 min cache timeout
//For better performence in Memory use set memoryCache(Cache.NONE) in this builder (If needed)
mInstance = new Picasso.Builder(context).memoryCache(lruCache).downloader(new OkHttp3Downloader(mOkHttp3Client)).indicatorsEnabled(true).build();
}
}
return mInstance;
}
public static void deletePicassoInstance()
{
mInstance = null;
}
public static void clearLRUCache()
{
if(lruCache!=null) {
lruCache.clear();
Log.d("FragmentCreate","clearing LRU cache");
}
lruCache = null;
}
public static void clearDiskCache(){
try {
if(diskCache!=null) {
diskCache.evictAll();
}
} catch (IOException e) {
e.printStackTrace();
}
diskCache = null;
}
}
I have installed a xamarin Picasso in my application, but wanted to clear the cached when the user logout my application. I can't find a ClearCache method which original Picasso library has one.
Not sure if you mean the memory or disk cache, so:
Disk cache:
Picasso defines its disk cache name as (PICASSO_CACHE = "picasso-cache"), so if you are not using a custom disk cache, you can delete the application's Picasso defined disk cache directly:
_picasso.Dispose(); // Done using Picasso
var cache = new File(BaseContext.ApplicationContext.CacheDir, "picasso-cache");
if (cache.Exists())
{
cache.Delete();
}
// Recreate if needed, but Picasso Build() will recreate it if it does not exist
if (!cache.Exists())
{
cache.Mkdirs();
}
If you are using your own LruCache or custom disk Cache implementation:
var cache = new File(BaseContext.ApplicationContext.CacheDir, "picasso-cache");
if (!cache.Exists())
cache.Mkdirs();
_lruCache = new LruCache((int)Runtime.GetRuntime().MaxMemory() / 1024 * 8);
_diskLruCache = new DiskLruCache(cache, 10 * 1024 * 1024);
_picasso = new Picasso.Builder(BaseContext).MemoryCache(_lruCache).Downloader(new OkHttpDownloader(_OkHttp3Client)).IndicatorsEnabled(true).Build();
Clear memory:
_lruCache.Clear();
Clear disk cache via your custom disk cache implementation:
_diskLruCache.Delete(); // Assumes Android style DiskLruCache
I am using Picasso for retrieving and showing images in my Android app. To avoid downloading all images over the network I am trying to add some images with the apk file, as sort of a pre-cached set of images. These images are stored in the assets folder and then copied to the Picasso cache folder on installation. This works as expected, but Picasso still download all images through the network and caches them as .0 and .1 files like this:
root#generic_x86:/data/data/com.my.app/files/images_cache #
ls
10.JPG
100.JPG
101.JPG
102.JPG
11.JPG
1f94664dec9a8c205b7dc50f8a6f3b79.0
1f94664dec9a8c205b7dc50f8a6f3b79.1
2.JPG
4621206beccad87a0fc01df2d080c644.0
4621206beccad87a0fc01df2d080c644.1
The *.JPG images are the ones I copied and the others are the Picasso cached images. Is there a way to make Picasso cache these images properly on installation?
If not, are there any other similar libraries that supports this kind of pre-caching?
Update: trying to cache from Assets folder
I tried making a small snippet that is run at first run of the app. The idea is to iterate the files in the given assets folder and fetch those images with Picasso. However, the below does not cache anything, although I end up in the onSuccess() method of the callback. The asset file names are correct. This is also verified by using the wrong folder name, which puts me in the onError() method of the callback.
I also tried loading it into a temporary ImageView, but it did do any difference.
public static boolean cacheImagesFromAssetsFolder(Context context)
{
boolean ok = false;
try
{
String[] images = context.getAssets().list("my_images");
for (String image : images)
{
Picasso.with(context).load("file:///android_asset/my_images/" + image).fetch(new Callback()
{
#Override
public void onSuccess()
{
// This is where I end up. Success, but nothing happens.
}
#Override
public void onError()
{
}
});
}
ok = true;
}
catch (Exception e)
{
e.printStackTrace();
}
return ok;
}
You could use File URI to request the Picasso to pick the image from your asset location instead of n/w.
Picasso.with(activity) //
.load(Uri.fromFile(file)) // Location of the image from asset folder
Update: How to use your own cache
import com.squareup.picasso.LruCache;
import com.squareup.picasso.Util;
LruCache imageCache = new LruCache(context);
Request request = Request.Builder(Uri.fromFile(asset_file), 0, null).build();
String cacheKey = Util.createKey(request, new StringBuilder());
imageCache.set(cacheKey, bitmap_object_of_asset_image);
Picasso.Builder(context)
.memoryCache(imageCache)
.build().load(asset_url).fetch(callback);
I need to manually add a bitmap to the cache specifying the URI (as key). If the request URI to download the image matches with the key, I need the pipeline to load the bitmap from the cache instead of making the network call.
I found this method Fresco.getImagePipelineFactory().getBitmapMemoryCache().cache( cacheKey, closeableReference). But how to get a closableReference to an arbitrary bitmap. Please help. Thank you.
If you are loading image with Fresco - yes:
public class OperationPostprocessor extends BasePostprocessor {
private int myParameter;
public OperationPostprocessor(int param) {
myParameter = param;
}
public void process(Bitmap bitmap) {
doSomething(myParameter);
}
public CacheKey getPostprocessorCacheKey() {
return new MyCacheKey(myParameter);
}
}
Cache key is MyCacheKey(myParameter)
You can use it when you are forming ImageRequest:
ImageRequest request = ImageRequestBuilder.newBuilderWithSource(photoUri)
.setPostprocessor(new OperationPostprocessor())
.build();
DraweeController controller = Fresco.newDraweeControllerBuilder()
.setOldController(simpleDraweeView.getController())
.setImageRequest(request)
.build();
simpleDraweeView.setController(controller);
Here you will use your postprocessor: .setPostprocessor(new OperationPostprocessor())
Resources:
http://frescolib.org/docs/modifying-image.html
http://frescolib.org/docs/resizing-rotating.html
One detail: here will be using fresco cache, but in Postprocessor.process(Bitmap) method, i think, you can add bitmap to your own cache.
I wrote a post explaining observations / experience with Fresco here.
Also check this post at medium
It has the solution to above problem too.