Unable to cache images using Picasso - android

i am using Picasso as image loading library in my android project.
I am using it in one fragment.At first it take some time to load profile image but when i open some other fragment and then come back to the same fragment.It again takes the same amount of time to load the same image.I think it is not caching image in the memory.
Below is my java code:
Picasso.with(getContext()).load(str).fetch(new Callback() {
#Override
public void onSuccess() {
Picasso.with(getContext()).load(str).placeholder(R.drawable.user).fit().into(cv);
}
#Override
public void onError() {
TastyToast.makeText(getActivity(),"Unable to load profile image.", TastyToast.LENGTH_SHORT,TastyToast.ERROR).show();
}
});

You have use it like this
Picasso.with(getContext()).load(str).networkPolicy(NetworkPolicy.OFFLINE).fetch(new Callback() {
#Override
public void onSuccess() {
//Picasso.with(getContext()).load(str).placeholder(R.drawable.user).fit().into(cv); don't need to use it here
}
#Override
public void onError() {
TastyToast.makeText(getActivity(),"Unable to load profile image.", TastyToast.LENGTH_SHORT,TastyToast.ERROR).show();
}
});

try to take off the callback in order to know if the image is loaded, instead use the code below that automatically change the image in case of error
Picasso.with(getAplicationContext()).load("image to load").placeholder("image to show while loading").error("image in case of error").into(view);
Note the context of the first parameter: Picasso's cache still alive only if the context still alive, so if you put the ApplicationContext in the first parameter, the context and the cache keap alive even if the activity is changing. otherwise if you put getActivityContext() in the first parameter, the cache keap alive untill the activity hes been destroy

if your app is using internet connection to load image then every time you come back or go to your image containing fragment it will download image from internet so better you should store images in your app database and try to use thumbnails instead of actual images if possible it will take less time to get load

Related

How to cancel Picasso fetch requests by tag?

When I enter an activity I'm calling this method:
private void cacheImagesAndLoadToMemory() {
for (City city : cities) {
Picasso.with(this).load(city.getImageUrl()).tag("fetch_images").fetch();
}
}
This fetches around 200 images which equates to around 45MB of data. Then I attach a fragment to this activity but when I leave the fragment I want the requests for the 200 images to be cancelled. So I have this code set up.
#Override
public void onDestroy() {
super.onDestroy();
Picasso.with(getActivity()).cancelTag("fetch_images");
}
But the fetch requests are not being cancelled. I have a bandwidth monitor on my status bar and can see that data keeps being pulled until all 200 images have been cached. Not sure what I'm doing wrong.
Seems to be a well known bug, cf. Github bug #1205.
Unfortunately Picasso project does not seem to move forward lately.

Glide not loading image or throwing error in AsyncTask

Glide is not loading my image synchronously inside my AsyncTask.
#Override
protected Boolean doInBackground(EventAppSetupModel... params) {
File icon = Glide.with(mContext).load("https://www.google.nl/images/branding/googlelogo/2x/googlelogo_color_272x92dp.png").downloadOnly(512, 512).get();
The AsyncTask just hangs. I am not getting any logging, even with the error logging enabled. When i set a listener, none of the methods of the listeners are ever called. If i do set a timeout of 15 seconds, it times out without giving me any other information. This happens for any image for any server.
How can I load and resize an image into a file with Glide synchronously?

Getting image download links from owncloud server

there is not much information out there for the newbies to owncloud.. not even here in Stack Overflow, a little background on what im trying to achieve is:
-Already managed to sync my project to the owncloud library via gradlle.
- The provided examples are not of much help for me you will see why.
I use this library https://github.com/bumptech/glide to stream images URLs to some imageviews in my app, as i was on a web server I had no problem but now that I moved to owncloud, I can do the same if i provide my app with the "download link" from the stored images.
That said, what I need is to some how be able to select the owncloud stored images(access the shared folder and download) by name and or read the download link from where ever is stored..
here is the use the glide library on my project
String url = null;
if (plato.getFoto_movil().equals("churrasco.jpg"))
{
url = "http://192.168.0.20/owncloud/index.php/s/EqX7LxLpUeBCzF4/download";
}
if (plato.getFoto_movil().equals("pizza.jpg"))
{
url = "http://192.168.0.20/owncloud/index.php/s/VGQJh6ii36PLGsN/download";
}
if (plato.getFoto_movil().equals("torta_chocolate.jpg"))
{
url = "http://192.168.0.20/owncloud/index.php/s/K0TaHRMPuMrs0Fx/download";
}
Glide.with(mContext).load(url).into(imageView);
which is sad because I had to manually get those URLs from my browser and it does not work with the newly added images from any othere device, so I need to be able to get any new image and show it too.
I have the library installed 100% and implemented but
private void startDownload(String filePath, File targetDirectory) {
DownloadRemoteFileOperation downloadOperation = new DownloadRemoteFileOperation(filePath, targetDirectory.getAbsolutePath());
downloadOperation.addDatatransferProgressListener((OnDatatransferProgressListener) mContext);
downloadOperation.execute( mClient, (OnRemoteOperationListener) mContext, mHandler);
}
#Override
public void onTransferProgress(long l, long l1, long l2, String s) {
mHandler.post( new Runnable() {
#Override
public void run() {
// do your UI updates about progress here
}
});
}
#Override
public void onRemoteOperationFinish(RemoteOperation remoteOperation, RemoteOperationResult remoteOperationResult) {
if (remoteOperation instanceof DownloadRemoteFileOperation) {
if (remoteOperationResult.isSuccess()) {
}
}
}
got those and
got also this two
mClient = OwnCloudClientFactory.createOwnCloudClient(serverUri,mContext,true);
mClient.setCredentials(OwnCloudCredentialsFactory.newBasicCredentials(username,password));
then I call the method
startDownload(plato.getFoto_movil(),downloadfolder);
the app crashes here when I call the startdowonload method
with the error java.lang.ClassCastException: com.eidotab.eidotab.MainActivity cannot be cast to com.owncloud.android.lib.common.network.OnDatatransferProgressListener
another relevant information is that im implementing the ownclod methods to
the viewholder of a recyclerview
public class VH extends RecyclerView.ViewHolder implements OnRemoteOperationListener, OnDatatransferProgressListener
but I could change to the main activity if needed, probably make it work from there but even if it does have success, donĀ“t know where or how to get the download links, like I said, I need the download link from every image stored in the server..
is this possible?
thanks in advance
I changed the implementation of the owncloud library to the main activity as suggested (and was the logical move) and everything went smooth.. worked at first try, I knew it was going to, the thing is that I didnt want to store the images on the device memory, I want to capture the download links which was my main concern but for now it is working since im streaming the images directly from the local sd to the imageview and that should give me some more time to investigate further in the matter whats the thing with the URLS...
Thanks cricket for your comments

RxImagePicker not calling completion if orientation changes when taking image

I'm using RxImagePicker to take photos in my portrait-only-forced app:
RxImagePicker.with(getActivity()).requestImage(Sources.CAMERA).subscribe(new Action1<Uri>() {
#Override
public void call(Uri uri) {
RxImageConverters.uriToBitmap(getActivity(), uri).subscribe(new Action1<Bitmap>() {
#Override
public void call(final Bitmap bitmap) {
getActivity().runOnUiThread(new Runnable() {
#Override
public void run() {
//i take over here if we ever get here...
}
});
}
});
}
});
If I take a picture without rotating the device, it works (although the image is rotated but that's another issue). However, if I take a picture in landscape orientation, uriToBitmap is never called. It's not my activity or fragment being restarted, as everything's state is preserved inside my app.
What am I doing wrong?
Acording to sources, RxImagePicker uses PublishSubject to communicate uri notifications to the client. Picker starts hidden activity, and that activity issues onCompleted() in it's onDestroy() callback. That callback is called on activity recreation in response to orientation change. Because Subject is Observable, it obeys to Observable contract, which states there should be no further notifications after onCompleted(), hence onNext() notifications following onCompleted() are ignored. There is another issue: onCompleted() is called twice when image is successfully picked. Seems like there is no workaround, possible solutions:
Fork library and fix aforementioned issues on your own
File issue on github so author can address them
Roll out your own solution ( best IMO)
It turned out to be something not-so-extraordinary.
I've simply forgot to update to the latest version and was using a few months old version of the library, which had the fix for the problem that I'm facing.
I've updated to the latest version and the problem went away.

How to I get the cached Bitmap I downloaded using Volley ImageLoader?

Problem: I've a X amount of ImageViews that I'm adding dynamically like this:
for (int i=2; i < result.size(); i++) {
// instantiate image view
ImageView mImageView = new ImageView(this);
mImageView.setScaleType(ImageView.ScaleType.FIT_CENTER);
mImageView.setBackgroundResource(R.drawable.selectable_background_theme);
mImageView.setOnClickListener(this);
// download image and display it
mImageLoader.get(result.get(i), ImageLoader.getImageListener(mImageView, R.drawable.ic_logo, R.drawable.ic_action_refresh));
// add images to container view
mLlDescContent.addView(mImageView);
}
What want to be able to click on the image and display it in another activity in full screen. I have read about a couple of ways such as passing the Uri or passing the actual Bitmap as a byte array.
Question: How do I get the Uri or the actual Bitmap I downloaded with Volley ImageLoader. The LruCache I'm using an BitmapLruCache I found here: Android Volley ImageLoader - BitmapLruCache parameter? . Can someone help me with this or any idea to accomplish my goal.
I tried this after the above code and nothing:
Bitmap mBitmap = VolleyInstance.getBitmapLruCache().getBitmap(result.get(2));
mIvAuthorImg.setImageBitmap(mBitmap);
Edit: If i re-request the image with:
mImageLoader.get(result.get(i), ImageLoader.getImageListener(mImageView, R.drawable.ic_logo, R.drawable.ic_action_refresh));
the image is loaded from the cache, BUT if I try to access the image straight from the cache with:
Bitmap mBitmap = VolleyInstance.getBitmapLruCache().getBitmap(result.get(2));
mIvAuthorImg.setImageBitmap(mBitmap);
the image don't load. I want to be able to manipulate the image, such as size an stuff before a pass it to the next activity.
Volley depends on your implementation of a cache for successful efficient caching.
The constructor for the ImageLoader takes in an ImageCache which is a simple interface in Volley to save and load bitmaps.
public ImageLoader(RequestQueue queue, ImageCache imageCache)
A quote from the Javadoc of ImageCache interface:
Simple cache adapter interface. If provided to the ImageLoader, it will be used as an L1 cache before dispatch to Volley. Implementations must not block. Implementation with an LruCache is recommended.
Darwind is right. If you request an image and it is present in the cache it will be loaded from the cache and not from the web. This should be the case for you since you're loading and presenting an image, which if clicked should be displayed from the cache in your new activity.
You say it's not working, perhaps your implementation isn't optimized for your use case. What kind of cache are you using? Do you have one centralized RequestQueue and ImageLoader as is recommended by the Volley team?
Take a look at this question, which isn't exactly the same as yours, yet could be helpful to you. It has a simple LRU cache implementation.
Hope that helps!
Edit:
The point of Volley is not to worry about implementation details. You want an image? it will load it for you the best and fastest way possible (from memory and if it's not there via network). That's exactly the way you should look at it. Retrieving the cache and then looking in it is not the right approach IMO.
Now, if you want to manipulate the bitmap, you have a few options, the best IMO being to implement your own Image Listener pass it to the get() method instead of the default one.
Something like this:
public class MyImageListener implements ImageListener() {
#Override
public void onErrorResponse(VolleyError error) {
// handle errors
}
#Override
public void onResponse(ImageContainer response, boolean isImmediate) {
Bitmap bitmap = response.getBitmap();
if (bitmap != null) {
//
// manipulations
//
// assuming mView is a reference to your ImageView
mView.setImageBitmap(bitmap);
} else {
// display placeholder or whatever you want
}
}
}
from the Javadoc:
The call flow is this:
Upon being attached to a request, onResponse(response, true) will be invoked to reflect any cached data that was already available. If
the data was available, response.getBitmap() will be non-null.
After a network response returns, only one of the following cases will happen:
onResponse(response, false) will be called if the image was loaded.
or
onErrorResponse will be called if there was an error loading the image.
There's a bug (I'm 70% sure it's a bug) in volley currently where if a cache-expiry isn't specified (say, if you're getting an image from an S3 bucket where you have a never-expires setting), you'll always redownload from the network.
You could get around this by checking out HttpHeaderParser, and changing the relevant bits (this isn't totally crazy, as you have to include the volley source code anyway) to:
// Cache-Control takes precedence over an Expires header, even if both exist and Expires
// is more restrictive.
if (hasCacheControl) {
softExpire = now + maxAge * 1000;
} else if (serverDate > 0 && serverExpires >= serverDate) {
// Default semantic for Expire header in HTTP specification is softExpire.
softExpire = now + (serverExpires - serverDate);
} else if (serverExpires == 0) {
softExpire = Long.MAX_VALUE;
}
Then you could just pass the Uri to the activity opening the thing as a parameter. This solution has the enviable property that if something goes wrong and something happens to the image between launching the activity and displaying the bitmap, you'll still redownload it and things will work appropriately. That'll probably never/seldom happen, but it's nice to know correctness is preserved.

Categories

Resources