Universal Image Loader: Can I use cache but also refresh it? - android

I'm loading dynamically generated images so I always want them to be up to date. But they take time to load so I also want to display a cached version while the updated one doesn't come.
How can I do this with Universal Image Loader?
More specifically, when I call "displayImage" I want it to do the following:
If a cached image exists display it right away.
Start downloading from the given url anyways.
When the image loading finishes, display it in the view replacing the cached image.
Update the cache.

So in the end I used an ImageLoadingListener as follows:
onLoadingStarted:
Check for cache when loading starts.
onLoadingComplete:
If no cache was found then do nothing. The request will be sent to network and cache will be updated naturally.
Otherwise clear cache and call displayImage again (no listener needed this time). The cached image will be shown in the view normally. Moreover, when the 2nd loading finishes, view and cache will be updated.
ImageLoader.getInstance().displayImage(imageUri, view, new SimpleImageLoadingListener() {
boolean cacheFound;
#Override
public void onLoadingStarted(String url, View view) {
List<String> memCache = MemoryCacheUtils.findCacheKeysForImageUri(url, ImageLoader.getInstance().getMemoryCache());
cacheFound = !memCache.isEmpty();
if (!cacheFound) {
File discCache = DiscCacheUtils.findInCache(url, ImageLoader.getInstance().getDiscCache());
if (discCache != null) {
cacheFound = discCache.exists();
}
}
}
#Override
public void onLoadingComplete(String imageUri, View view, Bitmap loadedImage) {
if (cacheFound) {
MemoryCacheUtils.removeFromCache(imageUri, ImageLoader.getInstance().getMemoryCache());
DiscCacheUtils.removeFromCache(imageUri, ImageLoader.getInstance().getDiscCache());
ImageLoader.getInstance().displayImage(imageUri, (ImageView) view);
}
}
});
}

You can use the ImageLoadingListener. This interface has 4 methods to override:
onLoadingStarted,onLoadingFailed,onLoadingComplete,onLoadingCancelled. In onLoadingStarted you can make the image the cached one, then on completed you change it.
So the call would look like this:
imgLoader.displayImage(url, myImageView,new ImageLoadingListener()
{
#Override
public void onLoadingStarted(String arg0, View arg1) {
//Display cached image if it exists
}
#Override
public void onLoadingFailed(String arg0, View arg1, FailReason arg2) {
// TODO Auto-generated method stub
}
#Override
public void onLoadingComplete(String arg0, View arg1, Bitmap arg2)
{
((ImageView)arg1).setBitmapImage(arg2);
}
#Override
public void onLoadingCancelled(String arg0, View arg1) {
// TODO Auto-generated method stub
}
});

private lateinit var options: DisplayImageOptions
options = DisplayImageOptions.Builder()
.considerExifParams(true)
.bitmapConfig(Bitmap.Config.RGB_565)
.cacheOnDisk(true)
.cacheInMemory(true)
.build()
ImageLoader.getInstance().displayImage(Model.img_url, itemView.ivPlayer, options)

Related

Images are not stored in the cache

I have this method, everything is worked perfectly but images always got from server and not load from cache! what happened ?
public static void makeImageRequest(String Unique_ID, final View parentView, final int id) {
String url = FILE_UPLOAD_FOLDER + Unique_ID + ".png";
final int defaultImageResId = R.drawable.user;
// Retrieves an image specified by the URL, displays it in the UI.
ImageCacheManager.getInstance().getImage(url, new ImageListener() {
#Override
public void onErrorResponse(VolleyError error) {
ImageView imageView = (ImageView) parentView.findViewById(id);
imageView.setImageResource(defaultImageResId);
}
#Override
public void onResponse(ImageContainer response, boolean isImmediate) {
if (response.getBitmap() != null) {
ImageView imageView = (ImageView) parentView.findViewById(id);
imageView.setImageBitmap(response.getBitmap());
} else if (defaultImageResId != 0) {
ImageView imageView = (ImageView) parentView.findViewById(id);
imageView.setImageResource(defaultImageResId);
}
}
});
}
Just use Picasso instead ImageCacheManager. Picasso is a powerful image downloading and caching library for Android. Images add much-needed context and visual flair to Android applications. Picasso allows for hassle-free image loading in your application—often in one line of code!
Picasso.with(context).load("http://i.imgur.com/DvpvklR.png").into(imageView);
Here also can manage whether the image is successfully downloaded or it fails:
Picasso.with(context)
.load("http://i.imgur.com/DvpvklR.png")
.into(imageView, new Callback() {
#Override
public void onSuccess() {
// your code
}
#Override
public void onError() {
// your code
}
});
You should only add this line in your gradle:
compile 'com.squareup.picasso:picasso:2.5.2'
Hope it helps!

Android Universal image loader with custom base image down-loader always gives total size as 51200

Hi I am building small android application in which I am using Universal image loader. I am using custom down loader class: It looks like as follow:
public class CustomUniversalImageDownloader extends BaseImageDownloader {
/**
* Constructor
* #param context
*/
public CustomUniversalImageDownloader(Context context) {
super(context);
}
#Override
public InputStream getStream(String imageUri, Object extra) throws IOException {
switch (Scheme.ofUri(imageUri)) {
case HTTP:
case HTTPS:
// here is my code ...
return new BufferedInputStream(response.getEntity().getContent(), BUFFER_SIZE);
case FILE:
return getStreamFromFile(imageUri, extra);
case CONTENT:
return getStreamFromContent(imageUri, extra);
case ASSETS:
return getStreamFromAssets(imageUri, extra);
case DRAWABLE:
return getStreamFromDrawable(imageUri, extra);
case UNKNOWN:
default:
return getStreamFromOtherSource(imageUri, extra);
}
}
On Displaying image I am doing following:
ImageCache.loader.displayImage(url, view, ImageCache.options, new SimpleImageLoadingListener() {
#Override
public void onLoadingStarted(String imageUri, View view) {
}
#Override
public void onLoadingFailed(String imageUri, View view,
FailReason failReason) {
}
#Override
public void onLoadingComplete(String imageUri, View view, Bitmap loadedImage) {
}
}, new ImageLoadingProgressListener() {
#Override
public void onProgressUpdate(String imageUri, View view, int current,
int total) {
// here my total always coming as 512000
Debug.print("inside this is image loading progress "+current+" this is total ... "+total);
Debug.print("inside this is image loading progress "+Math.round(100.0f * current / total));
}
}
);
}
So if I use default Base Image Downloader then it works fine. But If I use custom one then it is giving image total length always 512000. Am I missing anything?
Need Some Help. Thank you.
ImageLoaderConfiguration config = new ImageLoaderConfiguration.Builder(context)
...
.imageDownloader(new BaseImageLoaderCustom())
...
.build();
ImageLoader.getInstance().init(config);
from Nostra:
How set custom downloader in Universal Image Loader?
I got the answer. I looks it into BaseImageLoader and it is doing following thing:
ContentLengthInputStream(new BufferedInputStream(entity.getContent(), BUFFER_SIZE), (int)entity.getContentLength());
It works fine.

How to stop download of a single image

I'm creating an application where the user selects one item from a recycler view and this starts the download of a group of images.
I'm using universal image loader's loadImage method to fetch images for me which is working very well.
The problem is,if the user wants to cancel downloading this group of images (can be very network consuming) I cannot find a way to make ui stop only some of the images.
I'm aware of the method ImageLoader.cancelDisplayTask(), but as I'm using loadImage I have no ImageView or ImageAware available to send as a parameter to this task.
Also ImageLoader.stop() or ImageLoader.pause() stops all current downloads and I want to stop only the ones selected by the user.
How can I achieve this?
PS: A suggestion to some future development would be returning a pointer of the download task when using loadImage method. Maybe I'll look it myself when I have some time to contribute to this awesome library.
Here's my code for downloading an image.
private void downloadFile(final URL downloadURL,
final URL destinationURL,
final boolean isThumbnail,
final MyDownloadListener listener) {
final NewsData thisClass = this;
final ImageLoader il = ImageLoader.getInstance();
File imageFile = il.getDiskCache().get(destinationURL.toString());
if (imageFile.exists()) {
fallDownloadCompleted(this, isThumbnail);
return;
}
il.stop();
il.loadImage(
downloadURL.toString(),
null,
Application.getAppDisplayOptions(),
new SimpleImageLoadingListener() {
#Override
public void onLoadingStarted(String imageUri, View view) {
if (listener != null) {
listener.onLoadingStarted(thisClass);
}
}
#Override
public void onLoadingFailed(String imageUri, View view, FailReason failReason) {
fallDownloadFail(thisClass, failReason, isThumbnail);
}
#Override
public void onLoadingComplete(String imageUri, View view, Bitmap loadedImage) {
try {
il.getDiskCache().save(destinationURL.toString(), loadedImage);
if (isToday()) deleteImageFile(imageUri);
} catch (IOException e) {
deleteImageFile(imageUri);
fallDownloadFail(
thisClass,
new FailReason(FailReason.FailType.IO_ERROR, new Throwable()),
isThumbnail);
return;
}
fallDownloadCompleted(thisClass, isThumbnail);
}
},
new ImageLoadingProgressListener() {
#Override
public void onProgressUpdate(String imageUri, View view, int current, int total) {
float progress = 0;
if (total > 0 && numberOfTotalPages > 0) {
if (!isThumbnail) {
progress = numberOfAvailablePages / (float) numberOfTotalPages;
progress += (current / (float) total) / numberOfTotalPages;
} else {
progress = current / (float) total;
}
}
if (listener != null) {
listener.onProgressUpdate(thisClass, progress);
}
}
});
}
private ArrayList<ImageLoader> images = new ArrayList<ImageLoader>();
images.remove():
? Not familiar with ImageLoader class but I hope this helps
These might help
android: Universal Image Loader get drawable from string array
How to change array list to string array for using Universal Image Loader?
https://github.com/nostra13/Android-Universal-Image-Loader/issues/109
I managed to solve this issue with a small workaround.
I couldn't find a way to cancel a particular ImageLoader.loadImage() so what I had to do was use the normal ImageLoader.displayImage() by passing a NonViewAware class in place of the image view required as a parameter.
I then added this NonViewAware into an ArrayList<NonViewAware> to keep track of which images were being downloaded.
Finally when I wanted to cancel a display task I just called ImageLoader.cancelDisplayTask(NonViewAware) with one of the stored items from the list.

How to load JPEG as a BITMAP from server using Picasso

I've tried using the method:
bmp = (Bitmap) Picasso.with(Feed.this).load(IMAGE_URL+loadImageUrl).resize(width, width).get();
But I get a "Picasso DownloadResponseException" even when I take out the (Bitmap) typeCast
I've also tried:
Picasso.with(Feed.this).load(IMAGE_URL+image).resize(width, width).into(target);
With
private Target target = new Target() {
#Override
public void onBitmapFailed(Drawable arg0) {
// TODO Auto-generated method stub
Log.d("FAILED", "Bitmap Failed");
}
#Override
public void onPrepareLoad(Drawable arg0) {
// TODO Auto-generated method stub
}
#Override
public void onBitmapLoaded(Bitmap bmp, LoadedFrom arg1) {
RoundedCornersDrawable drawable = new RoundedCornersDrawable(getResources(), bmp);
theImage.setImageDrawable(drawable);
}
};
But it gives me nothing, the image doesn't load it just stays blank and the log message under the BitmapFailed method does not come up... The images stored on my server are of type "jpg".
Please help me
Figured it out. Turns out I had the wrong URL. Also make sure you Don't call that Picasso.get() method inside the UI thread...

Android download and persist a lot of images in background

In my Android application I would like to download a certain number of photos which are linked to points on a map. For example, I have ten points on a map and I have 5 or 6 photos for each point.
At the begining I get 5 or 6 URL (http://theimageurls.com/image.jpg) per point, and for each photo,
I want to download them
I want to save them in the device.
Of course, everything's done in background.
The problem is that sometimes my images are not persisted... but the problem is very irregular and can be encountered on whatever image...
here is my code :
For each point, loadPictures() is called :
private void loadPictures(final KickstartrGeolocPoint point) {
//Photos : get directory path
final File pointDir = FileUtils.getPointPhotoDir(getActivity(), point);
//set boolean to true if the point has photos not downloaded.
ArrayList<String> photosNotDownloaded = getPhotosNotDownloaded(point, pointDir);
if(photosNotDownloaded.size()!=0){
point.setPhoto(true);
kickstartrGeolocService.updatePoint(currentPoint);
}else{
fillPointData(point);
return;
}
//for each urls, download and save photo
for(final String url : photosNotDownloaded){
if (!Utils.isValidUrl(url)) continue;
BitmapUtils.getBitmapFromUrl(url, new OnBitmapRetrievedListener() {
#Override
public void bitmapRetrieved(Bitmap bitmap) {
LogWrapper.debug(getClass(), "Ready to be saved");
persistImageforPoint(point, pointDir, bitmap, FileUtils.getFileNameFromUrl(url));
}
#Override
public void onLoadingStarted(String imageUri, View view) {
LogWrapper.debug(getClass(), "Image downloading... " + imageUri);
//YOU CAN NOTIFY THE VIEW HERE
}
#Override
public void onLoadingFailed(String imageUri, View view, FailReason failReason) {
LogWrapper.debug(getClass(), "Loading failed : " + imageUri);
}
});
}
}
getBitmapFromUrl() is a static method which use an external library called https://github.com/nostra13/Android-Universal-Image-Loader.
getBitmapFromUrl() :
public static void getBitmapFromUrl(String url, final OnBitmapRetrievedListener listener) {
//final int maxSize = context.getResources().getDimensionPixelSize(R.dimen.icon_max_size);
ImageLoader.getInstance().loadImage(url, new ImageLoadingListener() {
#Override
public void onLoadingStarted(String imageUri, View view) {
listener.onLoadingStarted(imageUri,view);
}
#Override
public void onLoadingFailed(String imageUri, View view, FailReason failReason) {
listener.onLoadingFailed(imageUri,view,failReason);
}
#Override
public void onLoadingComplete(String imageUri, View view, Bitmap loadedImage) {
listener.bitmapRetrieved(loadedImage);
}
#Override
public void onLoadingCancelled(String imageUri, View view) {
//do nothing for the moment...
// TODO notify the UI
}
});
}
persistImageforPoint() is called to save the photo :
private void persistImageforPoint(KickstartrGeolocPoint point, File pointDir, Bitmap bitmap, String imageName) {
// Create a subfolder for each point with its id
if (!pointDir.exists()) {
if (!pointDir.mkdirs()) {
LogWrapper.debug(FileUtils.class, "Failed to create directory");
return;
}
}
final String fullPath = pointDir.getPath()+File.separator+FileUtils.getPointPhotoPrefix(point)+FileUtils.getFileNameFromUrl(imageName);
//save the file. Asynchronous task --> do not block the UI
new BitmapPersist(bitmap,fullPath, new OnBitmapPersistedListener() {
#Override
public void persistedSuccessfully() {
addPhotoView(fullPath);
}
#Override
public void errorInPersistance() {
LogWrapper.error(getClass(),"Error persisting image with path "+fullPath);
}
}).execute();
}
Here is my BitmapPersist class :
public class BitmapPersist extends AsyncTask<String, Void, Boolean> {
private String path;
private Bitmap bitmap;
private OnBitmapPersistedListener onBitmapPersistedListener;
public BitmapPersist(Bitmap bitmap, String path, OnBitmapPersistedListener onBitmapPersistedListener) {
this.bitmap=bitmap;
this.path=path;
this.onBitmapPersistedListener=onBitmapPersistedListener;
}
#Override
protected Boolean doInBackground(String... params) {
FileOutputStream out = null;
try {
out = new FileOutputStream(path);
bitmap.compress(Bitmap.CompressFormat.JPEG, 90, out);
return true;
} catch (Exception e) {
e.printStackTrace();
} finally {
try{
out.close();
} catch(Throwable ignore) {}
}
return false;
}
#Override
protected void onPostExecute(Boolean success) {
if (success)
onBitmapPersistedListener.persistedSuccessfully();
onBitmapPersistedListener.errorInPersistance();
}
}
Problem : Sometimes my pictures are not saved, sometimes the application crashes... although everything's done in background threads...
Thanks for your help.
EDIT : Maybe I can add precisions on the library I'm using to download images : It's Android-Universal-Image-Loader (link above). This library works with memory cache and... disk cache. Maybe I can look at this cache. Maybe I can change the path of disk cache and save my pictures with that. I'm also looking for someone who knows this library (developped by NOSTRA)... The documentation is quite succinct...
SOLUTION : Don't need to create 2 Asynctasks : Download the picture synchronously and then persist it in the same asynctask.

Categories

Resources