Custom Picasso Downloader

JPARDOGO
JPARDOGO
May 9, 2015 · 3 min read

Lately, I have been playing with the DropBox’s API and I faced a problem trying to display the image files thumbnails.

The problem

I didn’t have the URL of the thumbnail, so I couldn’t use it directly with Picasso as I used to do:

 Picasso.with(context).load(imageUrl).into(imageView);

When you request a folder content from the Dropbox API, you get the files metadata. One of the metadata values is called `thumbExists`, it indicate whether exist or not a thumbnail associate with this file.
If you want to get this thumbnail, there isn’t a URL, you need to call the method getThumbnailStream of the Dropbox API to get the thumbnail’s `InputStream`.

The problem comes when you want to use picasso to load the thumbnail’s `InputStream` but any load() method in the Picasso library accepts an `InputStream` as a parameter.

So, _What do we do if we want to load an InputStream with Picasso?_

The solution

We use a Custom Picasso Downloader

The guys at square added this cool feature in the library where you can just implement Downloader in your class and define the load method without exposing the functionality in the API directly.

Your custom load method will return a Response (which accept an InputStream or Bitmap argument in his constructor) that will be handle for Picasso.

You need to remember as well, that you need to use your own Picasso instance (using `new Picasso.Builder`) in order to specifying a custom Downloader.

The Code

public class DropBoxThumbDowloader implements Downloader {

private final DropBoxInteractor mDropBoxInteractor;

public DropBoxThumbDowloader(DropBoxInteractor dropBoxInteractor) {
mDropBoxInteractor = dropBoxInteractor;
}

@Override
public Response load(Uri uri, boolean localCacheOnly) throws IOException {
InputStream in = mDropBoxInteractor.getThumbnailStream(uri.toString());
return new Response(in, false, -1);
}
}

Here I have the custom downloader, and in my case, I passed an instance of my DropBoxInteractor to the constructor so I could call the Dropbox API form the load method to get the `InputStream` (The load method is NOT executed in the main thread). The Uri parameter in Downloader.load method is the one I will pass in Picasso.load later on. In this case, the Dropbox’s image path. Now, I create my own Picasso instance that will use the load method of the custom donwloader.

Picasso picassoInstance = new Picasso.Builder(context.getApplicationContext())
.downloader(new DropBoxThumbDowloader(dropBoxInteractor))
.build();

After the custom Picasso instance is built, I can load the dropbox thumbnails, this way.

//item.getItem().getPath() will be the uri parameter of Downloader.load
picassoInstance.load(item.getItem().getPath()).into(imageView);

When you create you own picasso downloader, make sure you don’t use with(Context context). That’s a static method that initializes the default Picasso instance.
You just need to call picassoInstance.load() directly after you have built your instance, like in the example above.

Conclusion

Don’t be afraid of creating your own custom downloaders, if the default Picasso instance doesn’t fulfil your requirements. This technique can be apply for other cases like this one, for example. This dynamic nature, makes Picasso even more awesome, and If you are not using this library yet. Please do, or at least give it a try. You won’t regret.

I hope you liked it, and keep Coding!

EDIT: In Picasso 2.4 this won’t be needed because there is a new RequestHandler API which let’s you register custom handlers. If you are interested about it, check the pull request.

    Written by

    JPARDOGO

    Android language writer and translator

    Welcome to a place where words matter. On Medium, smart voices and original ideas take center stage - with no ads in sight. Watch
    Follow all the topics you care about, and we’ll deliver the best stories for you to your homepage and inbox. Explore
    Get unlimited access to the best stories on Medium — and support writers while you’re at it. Just $5/month. Upgrade