1

I am wondering if there is any way to easily bundle a pre-cached folder of images by Picasso within an application.

My reason is to populate the app with some basic information, that is accessible even if the user has no/limited internet connection for the first time opening the app.

The cache/picasso-cache folder can be retrieved with $ adb pull /data/data/com.package.name/ ., but, unlike Realm ( https://realm.io/docs/objc/latest/#bundling-a-realm-with-an-app ), there seems to be no way to make Picasso be aware of it.

Possibly related: Using Picasso with custom disk cache

Community
  • 1
  • 1
caulitomaz
  • 2,141
  • 14
  • 20

1 Answers1

0

Although just using a pre-made cache would be really easy, I had second thoughts about it:

  1. The cache pulled from the emulator was rather large.

  2. It would suffice in my use-case to only show some thumbnails to the user when no internet was available. It could be much smaller.

My solution was:

  1. Import all essential images into your drawables.
  2. Try fetching the network-available / currently cached image with Picasso.
  3. If this fetching returns an error, then fill the ImageView with the locally available drawable (with Picasso!)

Pitfalls I fell into:

  1. Using Picasso's .placeholder(R.drawable.id) won't work because it will use the placeholder before loading the intended image, probably for saving resources/memory
  2. Using Picasso's .error(R.drawable.id) almost works, but Picasso can't transform placeholder and error images the same way they do with the asynchronously loaded images. This means .fit(), .centerInside() and other transformations won`t work. (see https://github.com/square/picasso/issues/337)

Loading variable resource names was essential to me. This happens on getThumbnail(). I named all my images product_thumbnail_{DB_ID}.

private int getThumbnail(Integer id)
{
    Resources res = context.getResources();
    int resID = res.getIdentifier("product_thumbnail_"+ id, "drawable", context.getPackageName());
    return resID;
}

Main logic inside my adapter:

final Context context = viewHolder.itemView.getContext();
final ImageView imageHolder = viewHolder.productImageHolder;
final int thumbnail = getThumbnail(product.getId());

if(thumbnail != 0)
{
    Picasso.with(context)
            .load(product.getImageUrl())
            .networkPolicy(NetworkPolicy.OFFLINE)
            .fit()
            .centerInside()
            .into(imageHolder, new com.squareup.picasso.Callback() {
                @Override
                public void onSuccess() { }

                @Override
                public void onError() {
                    useThumbnail(thumbnail, imageHolder, context);
                }
            });
}
else
{
    Picasso.with(viewHolder.itemView.getContext())
            .load(product.getImageUrl())
            .networkPolicy(NetworkPolicy.OFFLINE)
            .fit()
            .centerInside()
            .into(imageHolder);
}

useThumbnail():

private void useThumbnail(int thumb, ImageView imageHolder, Context context)
{
    Picasso.with(context)
            .load(thumb)
            .networkPolicy(NetworkPolicy.NO_CACHE)
            .fit()
            .centerInside()
            .into(imageHolder);
}
caulitomaz
  • 2,141
  • 14
  • 20