Skip to content

Instantly share code, notes, and snippets.

@orip
Last active July 18, 2018 08:39
Show Gist options
  • Save orip/6061163 to your computer and use it in GitHub Desktop.
Save orip/6061163 to your computer and use it in GitHub Desktop.
Working around https://github.com/square/okhttp/issues/184 for Picasso 2.x (older revisions for Picasso 1.1.1)
package com.example;
import android.content.Context;
import com.squareup.okhttp.HttpResponseCache;
import com.squareup.okhttp.OkHttpClient;
import com.squareup.picasso.OkHttpDownloader;
import com.squareup.picasso.Picasso;
import javax.net.ssl.SSLContext;
import java.io.File;
import java.io.IOException;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.security.GeneralSecurityException;
public class PicassoUtils {
private static Picasso singleton = null;
public static Picasso with(Context context) {
// Mimicking Picasso's new OkHttpLoader(context), but with our custom OkHttpClient
if (singleton == null) {
OkHttpClient client = createClient();
try {
client.setResponseCache(createResponseCache(context));
} catch (IOException ignored) {
}
singleton = new Picasso.Builder(context).downloader(new OkHttpDownloader(client)).build();
}
return singleton;
}
private static OkHttpClient createClient() {
OkHttpClient client = new OkHttpClient();
// Working around the libssl crash: https://github.com/square/okhttp/issues/184
SSLContext sslContext;
try {
sslContext = SSLContext.getInstance("TLS");
sslContext.init(null, null, null);
} catch (GeneralSecurityException e) {
throw new AssertionError(); // The system has no TLS. Just give up.
}
client.setSslSocketFactory(sslContext.getSocketFactory());
return client;
}
private static File createDefaultCacheDir(Context context) {
try {
final Class<?> clazz = Class.forName("com.squareup.picasso.Utils");
final Method method = clazz.getDeclaredMethod("createDefaultCacheDir", Context.class);
method.setAccessible(true);
return (File)method.invoke(null, context);
} catch (ClassNotFoundException e) {
throw new RuntimeException(e); // shouldn't happen
} catch (NoSuchMethodException e) {
throw new RuntimeException(e); // shouldn't happen
} catch (InvocationTargetException e) {
throw new RuntimeException(e); // shouldn't happen
} catch (IllegalAccessException e) {
throw new RuntimeException(e); // shouldn't happen
}
}
private static long calculateDiskCacheSize(File dir) {
try {
final Class<?> clazz = Class.forName("com.squareup.picasso.Utils");
final Method method = clazz.getDeclaredMethod("calculateDiskCacheSize", File.class);
method.setAccessible(true);
return (Long)method.invoke(null, dir);
} catch (ClassNotFoundException e) {
throw new RuntimeException(e); // shouldn't happen
} catch (NoSuchMethodException e) {
throw new RuntimeException(e); // shouldn't happen
} catch (InvocationTargetException e) {
throw new RuntimeException(e); // shouldn't happen
} catch (IllegalAccessException e) {
throw new RuntimeException(e); // shouldn't happen
}
}
private static HttpResponseCache createResponseCache(Context context) throws IOException {
File cacheDir = createDefaultCacheDir(context);
long maxSize = calculateDiskCacheSize(cacheDir);
return new HttpResponseCache(cacheDir, maxSize);
}
}
@tmoerman
Copy link

Thanks for this. Now I understand why my picasso caching didn't work properly.

/**
 * Create a new downloader that uses the specified OkHttp instance. A response cache will not be
 * automatically configured.
 */
public OkHttpDownloader(OkHttpClient client) {
  this.client = client;
}

@pimguilherme
Copy link

Thank you!

@canberkozcelik
Copy link

Isn't this cause a memory leak because of the static field of Picasso singleton?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment