By default, they will store into a local disk first for the extended keeping cache. Then the memory, for the instance usage of the cache. You can use the built-in indicator in Picasso to see where images form by enabling this.
A disk cache is a mechanism for improving the time it takes to read from or write to a hard disk. Today, the disk cache is usually included as part of the hard disk. A disk cache can also be a specified portion of random access memory (RAM).
When a program needs to access new data, the operating system first checks to see if the data is in the cache before reading it from the disk. Because computers can access data from RAM much faster than from a disk, disk caching can significantly increase performance.
Glide enables effective loading and caching of images. You can load images from a variety of sources such as files URIs, Android resources, bitmaps, drawables, etc. Just use the load() method to receive images.
This is what I did. Works well.
First add the OkHttp to the gradle build file of the app module:
compile 'com.squareup.picasso:picasso:2.5.2'
compile 'com.squareup.okhttp3:okhttp:3.10.0'
compile 'com.jakewharton.picasso:picasso2-okhttp3-downloader:1.1.0'
Then make a class extending Application
import android.app.Application;
import com.jakewharton.picasso.OkHttp3Downloader;
import com.squareup.picasso.Picasso;
public class Global extends Application {
@Override
public void onCreate() {
super.onCreate();
Picasso.Builder builder = new Picasso.Builder(this);
builder.downloader(new OkHttp3Downloader(this,Integer.MAX_VALUE));
Picasso built = builder.build();
built.setIndicatorsEnabled(true);
built.setLoggingEnabled(true);
Picasso.setSingletonInstance(built);
}
}
add it to the Manifest file as follows :
<application
android:name=".Global"
.. >
</application>
Now use Picasso as you normally would. No changes.
EDIT:
if you want to use cached images only. Call the library like this. I've noticed that if we don't add the networkPolicy, images won't show up in an fully offline start even if they are cached. The code below solves the problem.
Picasso.with(this)
.load(url)
.networkPolicy(NetworkPolicy.OFFLINE)
.into(imageView);
EDIT #2
the problem with the above code is that if you clear cache, Picasso will keep looking for it offline in cache and fail, the following code example looks at the local cache, if not found offline, it goes online and replenishes the cache.
Picasso.with(getActivity())
.load(imageUrl)
.networkPolicy(NetworkPolicy.OFFLINE)
.into(imageView, new Callback() {
@Override
public void onSuccess() {
}
@Override
public void onError() {
//Try again online if cache failed
Picasso.with(getActivity())
.load(posts.get(position).getImageUrl())
.error(R.drawable.header)
.into(imageView, new Callback() {
@Override
public void onSuccess() {
}
@Override
public void onError() {
Log.v("Picasso","Could not fetch image");
}
});
}
});
1) answer of first question : according to Picasso Doc for With() method
The global default Picasso instance returned from with() is automatically initialized with defaults that are suitable to most implementations.
- LRU memory cache of 15% the available application RAM
- Disk cache of 2% storage space up to 50MB but no less than 5MB.
But Disk Cache
operation for global Default Picasso is only available on API 14+
2) answer of second Question : Picasso
use the HTTP
client request to Disk Cache
operation So you can make your own http request header
has property Cache-Control
with max-age
And create your own Static Picasso Instance instead of default Picasso By using
1] HttpResponseCache (Note: Works only for API 13+ )
2] OkHttpClient (Works for all APIs)
Example for using OkHttpClient
to create your own Static Picasso class:
First create a new class to get your own singleton picasso
object
import android.content.Context;
import com.squareup.picasso.Downloader;
import com.squareup.picasso.OkHttpDownloader;
import com.squareup.picasso.Picasso;
public class PicassoCache {
/**
* Static Picasso Instance
*/
private static Picasso picassoInstance = null;
/**
* PicassoCache Constructor
*
* @param context application Context
*/
private PicassoCache (Context context) {
Downloader downloader = new OkHttpDownloader(context, Integer.MAX_VALUE);
Picasso.Builder builder = new Picasso.Builder(context);
builder.downloader(downloader);
picassoInstance = builder.build();
}
/**
* Get Singleton Picasso Instance
*
* @param context application Context
* @return Picasso instance
*/
public static Picasso getPicassoInstance (Context context) {
if (picassoInstance == null) {
new PicassoCache(context);
return picassoInstance;
}
return picassoInstance;
}
}
use your own singleton picasso
object Instead of Picasso.With()
PicassoCache.getPicassoInstance(getContext()).load(imagePath).into(imageView)
3) answer for third question : you do not need any disk permissions for disk Cache operations
References: Github issue about disk cache, two Questions has been answered by @jake-wharton -> Question1 and Question2
For caching, I would use OkHttp interceptors to gain control over caching policy. Check out this sample that's included in the OkHttp library.
RewriteResponseCacheControl.java
Here's how I'd use it with Picasso -
OkHttpClient okHttpClient = new OkHttpClient();
okHttpClient.networkInterceptors().add(new Interceptor() {
@Override
public Response intercept(Chain chain) throws IOException {
Response originalResponse = chain.proceed(chain.request());
return originalResponse.newBuilder().header("Cache-Control", "max-age=" + (60 * 60 * 24 * 365)).build();
}
});
okHttpClient.setCache(new Cache(mainActivity.getCacheDir(), Integer.MAX_VALUE));
OkHttpDownloader okHttpDownloader = new OkHttpDownloader(okHttpClient);
Picasso picasso = new Picasso.Builder(mainActivity).downloader(okHttpDownloader).build();
picasso.load(imageURL).into(viewHolder.image);
For the most updated version 2.71828 These are your answer.
Q1: Does it not have local disk cache?
A1: There is default caching within Picasso and the request flow just like this
App -> Memory -> Disk -> Server
Wherever they met their image first, they'll use that image and then stop the request flow. What about response flow? Don't worry, here it is.
Server -> Disk -> Memory -> App
By default, they will store into a local disk first for the extended keeping cache. Then the memory, for the instance usage of the cache.
You can use the built-in indicator in Picasso to see where images form by enabling this.
Picasso.get().setIndicatorEnabled(true);
It will show up a flag on the top left corner of your pictures.
Q2: How do I enable disk caching as I will be using the same image multiple times?
A2: You don't have to enable it. It's the default.
What you'll need to do is DISABLE it when you want your images always fresh. There is 2-way of disabled caching.
.memoryPolicy()
to NO_CACHE and/or NO_STORE and the flow will look like this.NO_CACHE will skip looking up images from memory.
App -> Disk -> Server
NO_STORE will skip store images in memory when the first load images.
Server -> Disk -> App
.networkPolicy()
to NO_CACHE and/or NO_STORE and the flow will look like this.NO_CACHE will skip looking up images from disk.
App -> Memory -> Server
NO_STORE will skip store images in the disk when the first load images.
Server -> Memory -> App
You can DISABLE neither for fully no caching images. Here is an example.
Picasso.get().load(imageUrl)
.memoryPolicy(MemoryPolicy.NO_CACHE,MemoryPolicy.NO_STORE)
.networkPolicy(NetworkPolicy.NO_CACHE, NetworkPolicy.NO_STORE)
.fit().into(banner);
The flow of fully no caching and no storing will look like this.
App -> Server //Request
Server -> App //Response
So, you may need this to minify your app storage usage also.
Q3: Do I need to add some disk permission to android manifest file?
A3: No, but don't forget to add the INTERNET permission for your HTTP request.
1) Picasso by default has cache (see ahmed hamdy answer)
2) If your really must take image from disk cache and then network I recommend to write your own downloader:
public class OkHttpDownloaderDiskCacheFirst extends OkHttpDownloader {
public OkHttpDownloaderDiskCacheFirst(OkHttpClient client) {
super(client);
}
@Override
public Response load(Uri uri, int networkPolicy) throws IOException {
Response responseDiskCache = null;
try {
responseDiskCache = super.load(uri, 1 << 2); //NetworkPolicy.OFFLINE
} catch (Exception ignored){} // ignore, handle null later
if (responseDiskCache == null || responseDiskCache.getContentLength()<=0){
return super.load(uri, networkPolicy); //user normal policy
} else {
return responseDiskCache;
}
}
}
And in Application singleton in method OnCreate use it with picasso:
OkHttpClient okHttpClient = new OkHttpClient();
okHttpClient.setCache(new Cache(getCacheDir(), 100 * 1024 * 1024)); //100 MB cache, use Integer.MAX_VALUE if it is too low
OkHttpDownloader downloader = new OkHttpDownloaderDiskCacheFirst(okHttpClient);
Picasso.Builder builder = new Picasso.Builder(this);
builder.downloader(downloader);
Picasso built = builder.build();
Picasso.setSingletonInstance(built);
3) No permissions needed for defalut application cache folder
I don't know how good that solution is but it is definitely THE EASY ONE i just used in my app and it is working fine
you load the image like that
public void loadImage (){
Picasso picasso = Picasso.get();
picasso.setIndicatorsEnabled(true);
picasso.load(quiz.getImageUrl()).into(quizImage);
}
You can get the bimap
like that
Bitmap bitmap = Picasso.get().load(quiz.getImageUrl()).get();
Now covert that Bitmap
into a JPG
file and store in the in the cache, below is complete code for getting the bimap and caching it
Thread thread = new Thread() {
public void run() {
File file = new File(getCacheDir() + "/" +member.getMemberId() + ".jpg");
try {
Bitmap bitmap = Picasso.get().load(uri).get();
FileOutputStream fOut = new FileOutputStream(file);
bitmap.compress(Bitmap.CompressFormat.JPEG, 100,new FileOutputStream(file));
fOut.flush();
fOut.close();
}
catch (Exception e) {
e.printStackTrace();
}
}
};
thread.start();
})
the get()
method of Piccasso
need to be called on separate thread , i am saving that image also on that same thread.
Once the image is saved you can get all the files like that
List<File> files = new LinkedList<>(Arrays.asList(context.getExternalCacheDir().listFiles()));
now you can find the file you are looking for like below
for(File file : files){
if(file.getName().equals("fileyouarelookingfor" + ".jpg")){ // you need the name of the file, for example you are storing user image and the his image name is same as his id , you can call getId() on user to get the file name
Picasso.get() // if file found then load it
.load(file)
.into(mThumbnailImage);
return; // return
}
// fetch it over the internet here because the file is not found
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With