Use a thumbnail as a placeholder for Picasso - android

From the UX point of view, it will be great to show the user a thumbnail first until the real image completes loading, then showing it to him, but Picasso uses only a resource file as the place holder like:
Picasso.with(context)
.load(url)
.placeholder(R.drawable.user_placeholder)
.into(imageView);
So, how can I use a thumbnail URL as the placeholder? , and if I should use Picasso twice, then how?
An issue is already opened on Picasso's github page with this request, but seems it won't be added to Picasso as per JakeWharton. So how could we do it with what's available in hand?

Thanks to raveN here & the comments on the original request on github, finally I've got a working solution:
Picasso.with(context)
.load(thumb) // thumbnail url goes here
.into(imageView, new Callback() {
#Override
public void onSuccess() {
Picasso.with(context)
.load(url) // image url goes here
.placeholder(imageView.getDrawable())
.into(imageView);
}
#Override
public void onError() {
}
});
The trick here is to get the drawable from the imageView (which is the thumbnail) after the first call & pass it as a placeholder to the second call
-- update --
I've made a blog post describing the whole scenario

You could write a simple helper which calls Picasso twice (as you mentioned).
I've not tested it, but it should go like
Picasso.with(context)
.load(thumbnailUrl)
.error(errorPlaceholderId)
.into(imageView, new Callback() {
#Override
public void onSuccess() {
// TODO Call Picasso once again here
}
#Override
public void onError() {
}
);
There are a couple of different ways to get your Picasso called twice. One method I could think of (again, not tested) is
public static void loadImageWithCallback(String url, Callback callback) {
Picasso.with(context)
.load(url)
.error(errorPlaceholderId)
.into(imageView, callback);
}
public static void loadImage(String url) {
Picasso.with(context)
.load(url)
.error(errorPlaceholderId)
.into(imageView);
}
loadImageWithCallback("http://example.com/mythumbnail.jpg", new Callback() {
#Override
public void onSuccess() {
loadImage("http://example.com/myRealImage.jpg");
}
#Override
public void onError() {
}
}
Edit: All I know is that Picasso provides this callback mechanism. I'm using it in my app to hide a ProgressBar that is displayed until the image is loaded. I'll hide it in success or error callbacks - so you'll have the option to get notified when image loading is done. Then you can simply call it again. I hope the above approach works.

I originally used AbdelHady's solution but found that the larger image is only loaded after the thumbnail is done loading so I came up with this instead.
Assuming you have a utility class in your project;
public final class U {
public static void picassoCombo(final RequestCreator thumbnail,
final RequestCreator large,
final ImageView imageView) {
Target target = new Target() {
#Override
public void onBitmapLoaded(Bitmap bitmap, Picasso.LoadedFrom from) {
imageView.setImageBitmap(bitmap);
}
#Override
public void onBitmapFailed(Drawable errorDrawable) {
imageView.setImageDrawable(errorDrawable);
}
#Override
public void onPrepareLoad(Drawable placeHolderDrawable) {
thumbnail.into(imageView);
}
};
imageView.setTag(target); // To prevent target from being garbage collected
large.into(target);
}
}
Usage:
U.picassoCombo(
Picasso.with(context)
.load("http://lorempixel.com/200/100/sports/1/")
.placeholder(R.drawable.ic_image_placeholder),
Picasso.with(context)
.load("http://lorempixel.com/800/400/sports/1/")
.error(R.drawable.ic_image_broken),
imageView
);
In the above example the placeholder is set first, the thumbnail url is set next, and regardless of whether the thumbnail request is done, successful, or failed, the large image request is set once it is done. If the large image request failed, then the error drawable is set.
The only issue is that if you use setIndicatorsEnabled(true) the debug indicators don't show for the large request. As far as I can tell this seems to be by design according to this issue convo

Related

Getting error on loading image from https url using Picasso library

In my application I'm trying to load image from an https URL using Picasso library.I am unable to load image into ImageView. I am using Picasso 2.5.2 and I am setting the image as follows:
Picasso.with(mContext)
.load(GlobalVariable.movieDetails.get(0).getVideo_cover_image())
.placeholder(R.drawable.animation_placeholder)
.error(R.drawable.animation_placeholder)
.into(iv_image);
Try this
if (TextUtils.isEmpty(imageUrl) && !isValidUrl(imageUrl)) {
iv_image.setImageResource(R.drawable.default);
} else {
Picasso.with(context)
.load(imageUrl)
.resize(70, 70)//if you want resize image
.centerInside()
.into(iv_image, new com.squareup.picasso.Callback() {
#Override
public void onSuccess() {
}
#Override
public void onError() {
iv_image.setImageResource(R.drawable.default);
}
});
}
validate URL
public static boolean isValidUrl(String string) {
boolean b = Patterns.WEB_URL.matcher(string).matches();
return b;
}
Picasso provide a listener for image loading.
Use below code and check image loading status either Success or Error.
Picasso.with(mContext)
.load(GlobalVariable.movieDetails.get(0).getVideo_cover_image())
.placeholder(R.drawable.animation_placeholder)
.error(R.drawable.animation_placeholder)
.into(iv_imagenew,
new com.squareup.picasso.Callback() {
#Override
public void onSuccess() {
//Image Loaded
}
#Override
public void onError() {
//Error while Loading
}
});
please use resize(horizontalSize, verticalSize) method of picaso to resize image. may be your image size is to large thats why it will not load so , please try resize(horizontalSize, verticalSize)
Picasso.with(context)
.load(GlobalVariable.movieDetails.get(0).getVideo_cover_image())
.placeholder(R.drawable.animation_placeholder)
.error(R.drawable.animation_placeholder)
.into(iv_image);
.resize(600, 200) // resizes the image to these dimensions (in pixel). does not respect aspect ratio
.into(imageViewResize);

Glide wont load all images in ViewHolder

So I have a RecyclerView with a custom adapter and I use Glide to download images from a URL when applicable. Relevant code snippet here:
#Override
public void onBindViewHolder(ViewHolder holder, int position) {
final Location location = mLocations.get(position);
holder.title.setText(location.getTitle());
if (location.hasImage()) {
String imageUrl = NetworkHelper.getImageUrl(getContext(),location.getImageName());
holder.image.setVisibility(View.VISIBLE);
// Use Glide for image loading
Glide.with(getContext())
.load(imageUrl)
.diskCacheStrategy(DiskCacheStrategy.ALL)
.centerCrop()
.into(new GlideDrawableImageViewTarget(holder.image) {
#Override
public void onLoadFailed(Exception e, Drawable errorDrawable) {
super.onLoadFailed(e, errorDrawable);
e.printStackTrace();
}
#Override
public void onResourceReady(GlideDrawable resource, GlideAnimation<? super GlideDrawable> animation) {
super.onResourceReady(resource, animation);
}
});
} else {
// Due to the nature of the RecyclerView, we need to ensure we clear
// out images to odd behavior.
Glide.clear(holder.image);
holder.image.setVisibility(View.GONE);
}
}
Problem is that the onResourceReady() method isnt always being called and hence not all images being loaded. Ive verified all the URL's being passed and they all seem fine. Is there a Glide specific issue here perhaps? If I take a URL that is not being loaded and hard code it into the imageUrl variable, its still not being downloaded, so there must be something specific to those images thats causing glide to fail. A timeout issue perhaps?
EDIT: I added the onLoadFailed method and it does hit, but the Exception is null, which is kinda weird. Basically same issue as described here: https://github.com/bumptech/glide/issues/741

Picasso - Download image once then load into multiple ImageView

Does anyone know how to download an image once then use the same Picasso instance to load into multiple ImageView? Right now I'm using a (pretty bad) workaround like the one below, in order to be sure the image is already cached and not downloaded again.
Picasso.with(container.getContext()).load(photo.getPath()).placeholder(R.drawable.placeholder_outfit).fit().centerCrop().into(image1, new Callback() {
#Override
public void onSuccess() {
Picasso.with(container.getContext()).load(photo.getPath()).placeholder(R.drawable.placeholder_outfit).fit().centerCrop().into(image2);
}
#Override
public void onError() {
}
});
You can do it like this:
Picasso.with(container.getContext())
.load(photo.getPath())
.placeholder(R.drawable.placeholder_outfit)
.fit()
.centerCrop().into(image1, new Callback() {
#Override
public void onSuccess() {
imageView2.setImageDrawable(image1.getDrawable()); //Get the ImageView's image (this won't download it, it will get the downloaded image) and set it to your second imageView.
}
#Override
public void onError() {
}
});
To use centerCrop(), just add:
imageView2.setScaleType(ImageView.ScaleType.CENTER_CROP);

Load Image one time with Picasso library

I am using Picasso library to get Image from an url.
My problem is when I load an Image for the first time and I exit out of my app and after I come back my app tries to load the Image again but I don't want it happen. Are there any other way to do that(load just one time the Image and in others time don't need to Internet for load)?
The issue with the above answers is that they only check the availability of the images in the disk cache, it does not cover the part if the image does not exist in the cache to go online and retrieve it.
First make a class that extends Application (You can name it whatever you want that does not interfere with your application, my convention is to use "Global").
public class Global extends Application {
#Override
public void onCreate() {
super.onCreate();
Picasso.Builder builder = new Picasso.Builder(this);
builder.downloader(new OkHttpDownloader(this,Integer.MAX_VALUE));
Picasso built = builder.build();
built.setIndicatorsEnabled(false);
built.setLoggingEnabled(true);
Picasso.setSingletonInstance(built);
}
}
Make sure you add dependancy for OkHttp library, it's developed by the same guys from Picasso
compile 'com.squareup.okhttp:okhttp:2.4.0'
and add the class in your Manifest file Applications tag :
android:name=".Global"
Then when you want to retrieve the image :
Picasso.with(context)
.load(Image URL)
.networkPolicy(NetworkPolicy.OFFLINE)
.into(imageView, new Callback() {
#Override
public void onSuccess() {
}
#Override
public void onError() {
//Try again online if cache failed
Picasso.with(context)
.load(Image URL)
.into(imageView, new Callback() {
#Override
public void onSuccess() {
}
#Override
public void onError() {
Log.v("Picasso","Could not fetch image");
}
});
}
});
The above method checks if the image is already cached, if not gets it from the internet.
try this:
Picasso.with(this).load(url).networkPolicy(NetworkPolicy.OFFLINE).into(imageView);
try this:
Picasso.with(this).invalidate(url);
Picasso.with(this)
.load(url)
.networkPolicy(
NetworkUtils.isConnected(this) ?
NetworkPolicy.NO_CACHE : NetworkPolicy.OFFLINE)
.resize(200, 200)
.centerCrop()
.placeholder(R.mipmap.ic_avatar)
.error(R.mipmap.ic_avatar)
.into(imageView);

How do I get the resulting bitmap of a picture after it has been resized into an imageview with picasso

I'm trying to re-size a picture from my gallery to fit an imageview and save its bitmap after the fit so I can upload it to my Parse database on the press of an "add" button. Currently, when "add" is pressed, I check if the bitmap is null, and if it isn't, convert it to a Parsefile to be saved in my Parse database. Adding to the database works (I tested this without using Picasso), but I'm not sure how to get the bitmap if I use Picasso to resize and load. I tried creating a Target and using its callbacks, but I can't use .fit() on a target. I've resorted to using a callback, but I was hoping for a better way to achieve the saving of the bitmap.
Here's what I'm doing right now, trying to get the bitmap from the imageview after it's been loaded:
if(uri != null) {
Picasso.with(mContext).load(uri).skipMemoryCache().fit().centerCrop().into(imgPreview, new Callback() {
#Override
public void onSuccess() {
mBitmap = ((BitmapDrawable)imgPreview.getDrawable()).getBitmap();
}
#Override
public void onError() {
// TODO Auto-generated method stub
}
});
}
You can use a callback
Picasso.with(context)
.load(absolutePath)
.fit()
.noFade()
.centerInside()
.placeholder(R.drawable.image_holder)
.memoryPolicy(MemoryPolicy.NO_CACHE)
.into(imageView, new Callback() {
#Override
public void onSuccess() {
// You can do anything here because your imageView now has the bitmap set
}
#Override
public void onError() {
}
});

Categories

Resources