Back to Blog

Setting up the Android Google Volley ImageLoader for NetworkImageView

October 8, 2013

By Matt Mombrea
29 Comments

Google Volley is awesome. If you’re an Android developer and you’ve done AsyncTask and HttpClient stuff (and there is no avoiding it), prepare for a huge relief once you get up and running with Volley. All of the leg work has been handled for you when it comes to managing the threads, dealing with a JSON response, handling errors, and way more.

Using NetworkImageView

Included with the library is an extremely useful object called NetworkImageView. NetworkImageView is meant to be a direct replacement for the standard ImageView in scenarios when your image resource is coming from a network location (i.e. URL) rather than a static resource. In your layout file, it’s as simple as changing the element from ImageView to NetworkImageView, for example:

    <ImageView
        android:id="@+id/twitter_avatar"
        android:layout_width="48dp"
        android:layout_height="48dp"
        android:layout_alignParentBottom="true"
        android:layout_alignParentTop="true"
        android:layout_marginRight="6dip"
     />

Becomes

    <com.android.volley.toolbox.NetworkImageView
        android:id="@+id/twitter_avatar"
        android:layout_width="48dp"
        android:layout_height="48dp"
        android:layout_alignParentBottom="true"
        android:layout_alignParentTop="true"
        android:layout_marginRight="6dip"
     />

The next step is to populate your element programatically using the URL of the image. This is straight forward as well, at least at first glance:

    NetworkImageView avatar = (NetworkImageView)view.findViewById(R.id.twitter_avatar);
    avatar.setImageUrl("http://someurl.com/image.png",mImageLoader);

And that’s where just about every example on the web leaves it. But what about that mImageLoader variable?

Setting up the ImageLoader

It’s more complicated than it appears. The ImageLoader class is actually responsible for setting up caching on the device, and initializing the object isn’t trivial. To get going with the ImageLoader, start by declaring private variables for use in your class:

private RequestQueue mRequestQueue;
private ImageLoader mImageLoader;

Then in your constructor or OnCreate() method, initialize the objects using the following:

        mRequestQueue = Volley.newRequestQueue(context);
        mImageLoader = new ImageLoader(mRequestQueue, new ImageLoader.ImageCache() {
            private final LruCache<String, Bitmap> mCache = new LruCache<String, Bitmap>(10);
            public void putBitmap(String url, Bitmap bitmap) {
                mCache.put(url, bitmap);
            }
            public Bitmap getBitmap(String url) {
                return mCache.get(url);
            }
        });

Now you’re free to use the magical NetworkImageView.setImageUrl() method as intended:

    NetworkImageView avatar = (NetworkImageView)view.findViewById(R.id.twitter_avatar);
    avatar.setImageUrl("http://someurl.com/image.png",mImageLoader);

Singleton Pattern

Google recommends that you use a common RequestQueue object for your app in the form of a Singleton. This is also something that is glossed over in examples, so have another one on us.

VolleySingleton.java

import android.content.Context;
package com.company.myapplication;

import android.content.Context;
import android.graphics.Bitmap;
import android.support.v4.util.LruCache;

import com.android.volley.RequestQueue;
import com.android.volley.toolbox.ImageLoader;
import com.android.volley.toolbox.Volley;

public class VolleySingleton {
    private static VolleySingleton mInstance = null;
    private RequestQueue mRequestQueue;
    private ImageLoader mImageLoader;

    private VolleySingleton(){
        mRequestQueue = Volley.newRequestQueue(MyApplication.getAppContext());
        mImageLoader = new ImageLoader(this.mRequestQueue, new ImageLoader.ImageCache() {
            private final LruCache<String, Bitmap> mCache = new LruCache<String, Bitmap>(10);
            public void putBitmap(String url, Bitmap bitmap) {
                mCache.put(url, bitmap);
            }
            public Bitmap getBitmap(String url) {
                return mCache.get(url);
            }
        });
    }

    public static VolleySingleton getInstance(){
        if(mInstance == null){
            mInstance = new VolleySingleton();
        }
        return mInstance;
    }

    public RequestQueue getRequestQueue(){
        return this.mRequestQueue;
    }

    public ImageLoader getImageLoader(){
        return this.mImageLoader;
    }

}

You’ll need to implement a static application context in a class which extends Application. Then, update line 15 of VolleySingleton.java to call your static context getter method. An example of what this application class might look like can be found here: MyApplication.java

Using the Singleton is as simple as:

RequestQueue queue = VolleySingleton.getInstance().getRequestQueue();

//or

mImageLoader = VolleySingleton.getInstance().getImageLoader();

Download

Get the singleton and instructions from our GitHub repo here https://github.com/CypressNorth/Volley-Singleton

Matt Mombrea

Matt Mombrea

Matt is a longtime entrepreneur and software engineer. He also sits on the board of Computer Science at SUNY Fredonia. Born and raised in Buffalo, Matt is passionate about building and maintaining great businesses in Buffalo. Apart from leading Cypress North, Matt architects our company’s datacenter, engineers dozens of custom applications, and directs the rest of the development team.

See Matt's Most Recent Posts

Share this post

29 comments

gordonpassy August 10, 2015Reply

Very helpful

haoc June 5, 2015Reply

Nice post!
Since this is a singleton pattern, I think it is necessary to make sure it is thread safe.:)

umeshisran405 May 14, 2015Reply

Nice post on volley.. The discussions help a lot..

Vladimir Makarov January 29, 2015Reply

hi, Matthew Mombrea, its a fantastic article but I have a few doubts, if the ImageCache works as intended , why are people discussing issues and shortcomings about the ImageCaching here http://stackoverflow.com/questions/21848749/volley-image-caching and infact going to the extent of using a custom DiskBasedCache made by Jake Wharton, the founder of sherlockactionbar, does the LruCache work inside an adapter such as a BaseAdapter’s getView or RecyclerView.Adapter’s onBindViewHolder , I have used other libraries in the past such as Picasso and UniversalImageLoader to manage images downloaded from a url inside a ListView or RecyclerView, however I feel Volley is missing something, can you please enlighten me on it, thanks in advance

Matthew Mombrea January 29, 2015Reply

Vlad,

The reason for the confusion is the lack of documentation on how the cache is supposed to be used with Volley. In that StackOverflow thread, the question shows the person using the LruCache within the OnCreate method of a fragment. It doesn’t look as if he’s creating a VolleySingleton using a single context for cache, or even the fragment for that matter. If you don’t use a singleton and you don’t use a common context, the cache won’t work as you expect.

Even using a singleton, you need to be careful about the context you give it. If you look back in this comment thread, Jean-François Cartier caught a mistake in my code related to the cache context. It’s since been updated and works as you’d expect.

Here’s the link to the repo showing how to use the singleton pattern with volley + LruCache:
https://github.com/CypressNorth/Volley-Singleton

Sam Harris October 9, 2014Reply

Has anyone used the ImageLoader for Https requests. I need to put some basic authorization into my requests but don’t see a simple way to do that with the ImageLoader

Ashish September 5, 2014Reply

The way volley works Its totally disaster.If You are working with high resolution image and you are downloading 500 hundred images,It never work.OutOfMemory error does not handled by volley.

Matthew Mombrea September 5, 2014Reply

Ashish,

That is not a problem with volley, it’s a problem with the strategy. All mobile applications have a limited amount of memory to work with which is governed by the OS. You need to be careful with the size and number of images that you’re loading into memory and displaying at once. No library will help you load 500 high-res images onto a mobile app at once.

Deep Shah July 5, 2014Reply

It’s nice article .

The best way to maintain volley core objects and request queue is, making them global by creating a singleton class which extends Application object and create your singleton implementation within this class .

Jean-François Cartier March 2, 2014Reply

The problem I see using a Singleton here is that the constructor takes one argument (a Context object). An object requiring a parameter in the constructor cannot be a Singleton per se. Let’s say we have ActivityA and ActivityB. ActivityA calls VolleySingleton.getInstance(this). Later, ActivityB calls VolleySingleton.getInstance(this). It will return the instance created by ActivityA since mInstance != null. What if the context is not available anymore (i.e. ActivityA has been destroyed). Does it crash?

Matthew Mombrea March 2, 2014Reply

Jean-Francois,

Very good point. I’ll have to fire up the debugger to see exactly what’s going on in that scenario. I’m using this VolleySingleton in several Activities and haven’t experienced any issues yet. I suspect (but it’s just a guess at this point) that each time a new Activity is loaded the previous Activity is unloaded, along with the instance of the singleton. In that way, the singleton would be scoped to the life of that activity. I have no idea if that’s true or not but when I have a moment I’ll step through an example and figure it out. If it does indeed crash between Activities, I’ll be sure to update this post and the Github. Thank you!

Jean-François Cartier March 2, 2014Reply

I don’t think that the singleton would be scoped to the lifecycle of an Activity. To resolve this I thought about creating the singleton in an Application object (https://developer.android.com/reference/android/app/Application.html). However, reading the documentation about this class lead me to the solution:
“If your singleton needs a global context (for example to register broadcast receivers), the function to retrieve it can be given a Context which internally uses Context.getApplicationContext() when first constructing the singleton.”

From what I understand passing any Context would do, but I think that it would even be better if the constructor and getInstance would not require any Context and use Context.getApplicationContext() internally in the constructor. What do you think?

Matthew Mombrea March 2, 2014Reply

I think you’re right, and that sounds like a good solution. Looking at the Volley newRequestQueue method (which requires the context), the comment for the context is “context A [email protected] Context} to use for creating the cache dir.”

If it’s only being used to get/create the cache directory, the application context seems appropriate.

Jean-François Cartier March 2, 2014

Totally agree.

Matthew Mombrea March 4, 2014

The Github repo has been updated with your contribution, thanks! I tested out the situation and, while the different contexts didn’t crash the app, they also were generating different cache files, effectively limiting the loader cache to a single Activity rather than the whole application. This solution is much better.

Vijay Dhama February 26, 2014Reply

Thanks for the post. Singleton Pattern seems to make sense. Is it not common for networkimageview to face OutOfMemory errors?

Matthew Mombrea February 26, 2014Reply

I haven’t experienced any out of memory issues to date but I can’t say I know for sure

Fabio February 20, 2014Reply

Really brief and concise, but great !! You saved me from a good headache here.
PS: It would be great if you post the files for non advanced users, it used to hep me a lot.

Matthew Mombrea February 27, 2014Reply

Fabio,

Added a link to our GitHub repo with the file
https://github.com/CypressNorth/Volley-Singleton

abi V.R January 28, 2014Reply

Also how to set a place holder till the image is loaded and is there is any listener for checking whether the image is set to Image view . Consider a condition in which a progress indicator is shown until image is loded ti view.

abi V.R January 28, 2014Reply

http://stackoverflow.com/questions/16682595/android-volley-imageloader-bitmaplrucache-parameter

check this one to make it perfect , and allow the size of cache

soma January 6, 2014Reply

Thanks for this great Article, I would recomend you to store the RequestQueue in Application or MainActivity and acces it from there via a getter. THANK YOU VERY MUCH!

Matthew Mombrea January 6, 2014Reply

You’re welcome. I think that the singleton pattern is the recommended way to handle the RequestQueue.

Krste November 28, 2013Reply

Great post, Thanks 😉

bertslike November 28, 2013Reply

Thank you so much for this post, I finally managed to understand the whole concept!

Vivek Bhusal November 13, 2013Reply

This is the perfect example I have found about ImageView Loader on the Internet till date.. Thanks for sharing

Shervin Asgari November 6, 2013Reply

Thank you for this. This cleared up a few things for me.
Now I will use Volley in my application.

Delton Childs November 3, 2013Reply

How is it that this article has no comments… this code is epic. It works perfectly. It’s so hard to find good documentation on Volley and the whole image loading with recycled views is a huge hurdle for beginners. I can’t thank you enough!

Kumar Saurav October 11, 2013Reply

Dumping volley for Picasso and retrofit combo.

Leave a Reply

Search our blog

Start A Project

Categories

What's next?

Well...you might like one of these

Article

The Mobile Search Analytics Report: Our...

Sigh. To think that there was once a time that Custom...

Read article

Article

Country Ham, Hip Hop & Halloween:...

For your convenience, seasonally-themed puns have been...

Read article

Article

The Retargeting Playbook: The Ultimate...

As an internet user, you’ve likely become accustomed to...

Read article