I know Volley is supposed to make downloading and caching images mindlessly simple but yet I have been struggling for hours to properly implement it. I've looked around the net as well as the many articles on stackoverflow regarding volley but none of the examples I've found seem to work for me.
I only want to use volley to download and cache images from a given url, not to do any HTTP JSON REST handling. Just to take given urls, download the bitmaps and set them to the imageview then add them to the cache.
This has been my latest attempt so far. How do I load and cache images with volley correctly?
if (data.getImageUrl() != null) {
try {
holder.thumbnail.setTag(data.getImageUrl());
Cache cache = ImgController.getInstance().getRequestQueue().getCache();
Cache.Entry entry = cache.get(data.getImageUrl());
if (entry != null) {
try {
String cImg = new String(entry.data, "UTF-8");
LruBitmapCache bitmapCache = new LruBitmapCache();
holder.thumbnail.setImageBitmap(bitmapCache.getBitmap(cImg));
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
}
} else {
ImageLoader imageLoader = ImgController.getInstance().getImageLoader();
imageLoader.get(data.getImageUrl(), new ImageListener() {
@Override
public void onErrorResponse(VolleyError error) {
holder.thumbnail.setImageResource(R.drawable.filler_icon);
}
@Override
public void onResponse(ImageLoader.ImageContainer response, boolean arg1) {
if (response.getBitmap() != null) {
// load image into imageview
holder.thumbnail.setImageBitmap(response.getBitmap());
}
}
});
}
return convertView;
} catch (Exception e) {
e.printStackTrace();
Log.v(DEBUG_TAG, "no image: ", e);
holder.thumbnail.setImageResource(R.drawable.filler_icon);
}
}else {
return null;
}
return convertView;
}
When I run this I get a NullPointerException pointing to this line
Cache cache = ImgController.getInstance().getRequestQueue().getCache();
I've setup the following singleton class to handle requests
public class ImgController extends Application {
public static final String TAG = ImgController.class.getSimpleName();
private RequestQueue requestQueue;
private ImageLoader imageLoader;
private static ImgController instance;
@Override
public void onCreate() {
super.onCreate();
instance = this;
}
public static synchronized ImgController getInstance(){
return instance;
}
public RequestQueue getRequestQueue(){
if(requestQueue == null){
requestQueue = Volley.newRequestQueue(getApplicationContext());
}
return this.requestQueue;
}
public ImageLoader getImageLoader(){
getRequestQueue();
if(imageLoader == null){
imageLoader = new ImageLoader(this.requestQueue, new LruBitmapCache());
}
return this.imageLoader;
}
public <T> void addToRequestQueue(Request<T> req, String tag) {
// set the default tag if tag is empty
req.setTag(TextUtils.isEmpty(tag) ? TAG : tag);
getRequestQueue().add(req);
}
public <T> void addToRequestQueue(Request<T> req) {
req.setTag(TAG);
getRequestQueue().add(req);
}
public void cancelPendingRequests(Object tag) {
if (requestQueue != null) {
requestQueue.cancelAll(tag);
}
}
}
as well as the following LruBitmapCache class
public class LruBitmapCache extends LruCache<String, Bitmap> implements ImageLoader.ImageCache {
public static int getDefaultLruCacheSize(){
final int maxMemory = (int) (Runtime.getRuntime().maxMemory() / 1024);
final int cacheSize = maxMemory / 8;
return cacheSize;
}
public LruBitmapCache() {
this(getDefaultLruCacheSize());
}
public LruBitmapCache(int maxSize) {
super(maxSize);
}
@Override
public Bitmap getBitmap(String url) {
return get(url);
}
@Override
public void putBitmap(String url, Bitmap bitmap) {
put (url, bitmap);
}
}
(Sorry for poor english skill ^^;)
YEAH! Volley is VERY SIMPLE. you don't need to think about cache hit, image loading etc...
just use
NetworkImageView
. Belows are example.layout_example.xml
MainActivity.java
NetworkImageView
automatically loads image from background queue and cancel request when this view is detachedusing ImageLoader
. andImageLoader
automatically uses memory lru cache and disk cache.NetworkImageView
is best solution for you.Additional Information
ImageRequest is deprecated so I am doing it as follows:
Step 1: Make Application class as below first
Step 2: Now make a image request as follows from any activity or fragment
I have a more simple solution for displaying the image from url and storing it in cache. Without adding additional classes, only MainActivity. probably it will help somebody...
Here is my XML that displays only ImageView
And here is my MainAvtivity.java:
Don't forget to add
<uses-permission android:name="android.permission.INTERNET" />
in Manifest.xml andcompile 'com.android.volley:volley:1.0.0'
in build.gradle dependenciesA callback for Image Request is available for Volley, you can use the Following code below.
This is covered in the documentation: https://developer.android.com/training/volley/request.html#request-image