I am using Glide v4 to load a bitmap that can then be used to as a marker on the map. When I use the deprecated SimpleTarget like so everything works fine.
GlideApp.with(getContext()).asBitmap().load(url)
.into(new SimpleTarget<Bitmap>() {
#Override
public void onResourceReady(#NonNull Bitmap resource, #Nullable Transition<? super Bitmap> transition) {
// load bitmap as marker
}
});
When I try removing the deprecated code and using Target<Bitmap> like given below I can see the onLoadStarted gets called but the onResourceReady is never called neither is the onLoadFailed.
GlideApp.with(getContext()).asBitmap()
.load(UrlHelper.createUrl(poi.getMapMarker()))
.into(marketBitmap);
private Target<Bitmap> marketBitmap = new Target<Bitmap>() {
#Override
public void onLoadStarted(#Nullable Drawable placeholder) {
Log.d("GlideMar", "marker load started");
}
#Override
public void onLoadFailed(#Nullable Drawable errorDrawable) {
Log.e("GlideMar", "marker load failed");
}
#Override
public void onResourceReady(#NonNull Bitmap resource, #Nullable Transition<? super Bitmap> transition) {
Log.d("GlideMar", "onResourceReady");
}
#Override
public void onLoadCleared(#Nullable Drawable placeholder) {
Log.d("GlideMar", "marker onLoadCleared");
}
#Override
public void getSize(#NonNull SizeReadyCallback cb) {
}
#Override
public void removeCallback(#NonNull SizeReadyCallback cb) {
}
#Override
public void setRequest(#Nullable Request request) {
}
#Nullable
#Override
public Request getRequest() {
return null;
}
#Override
public void onStart() {
Log.d("GlideMar", "marker onStart");
}
#Override
public void onStop() {
Log.d("GlideMar", "marker onStop");
}
#Override
public void onDestroy() {
Log.d("GlideMar", "marker onDestroy");
}
};
From Glide Custom Targets documentation.
If you’re using a custom Target and you’re not loading into a View
that would allow you to subclass ViewTarget, you’ll need to implement
the getSize() method.
So in your case just put the below code in getSize method
#Override
public void getSize(SizeReadyCallback cb) {
cb.onSizeReady(Target.SIZE_ORIGINAL, Target.SIZE_ORIGINAL);
}
Now the onResourceReady method will be called when you run the app.
Related
I am working on the project to create the stories like whatsapp or instagram.
we are using the library from Github
Our image are loaded from firebase.
but the problem is that stories start with loading the image because image size is large.
#Override
public void onFirebaseLoadSuccess(final List<Movie> movieList) {
storiesProgressView.setStoriesCount(movieList.size());
storiesProgressView.setStoryDuration(1500L);
Picasso.get().load(movieList.get(counter).getImage()).into(imageView, new Callback() {
#Override
public void onSuccess() {
progressBar.setVisibility(View.GONE);
storiesProgressView.startStories();
}
#Override
public void onError(Exception e) {
}
});
storiesProgressView.setStoriesListener(new StoriesProgressView.StoriesListener() {
#Override
public void onNext() {
if(counter < movieList.size()){
counter++;
Picasso.get().load(movieList.get(counter).getImage()).into(imageView);
}
}
#Override
public void onPrev() {
if(counter > 0){
counter--;
Picasso.get().load(movieList.get(counter).getImage()).into(imageView);
}
}
#Override
public void onComplete() {
counter = 0;
Toast.makeText(MainActivity.this,"Completed!",Toast.LENGTH_LONG).show();
finish();
}
});
}
Picasso doesn't has a function to check when load started so i highly recommend you to use Glide instead of Picasso.
Here, you can show progress bar when image loading is started via onLoadStarted() function :
Glide.with(this).load(movieList.get(counter).getImage()).into(new Target<GlideDrawable>() {
#Override
public void onStart() {
}
#Override
public void onStop() {
}
#Override
public void onDestroy() {
}
#Override
public void onLoadStarted(Drawable placeholder) {
progressBar.setVisibility(View.VISIBLE);
}
#Override
public void onLoadFailed(Exception e, Drawable errorDrawable) {
}
#Override
public void onResourceReady(GlideDrawable resource, GlideAnimation<? super GlideDrawable> glideAnimation) {
progressBar.setVisibility(View.GONE);
imageView.setImageDrawable(resource);
storiesProgressView.startStories();
}
#Override
public void onLoadCleared(Drawable placeholder) {
}
#Override
public void getSize(SizeReadyCallback cb) {
}
#Override
public void setRequest(Request request) {
}
#Override
public Request getRequest() {
return null;
}
});
Till now I have done the following, if I omit the circular image creation part it works fine, but I must show a circular image in actionbar
here is what I have tried so far, any help will be highly appreciated
Glide.with(mContext)
.load(doctorDetailsList.get(0).getDoc_imgurl().replace("200x200", Measuredwidth + "x" + Measuredwidth))
.placeholder(R.drawable.no_image)
.override(Measuredwidth, Measuredwidth)
.into(new Target<GlideDrawable>()
{
#Override
public void onLoadStarted(Drawable placeholder)
{
}
#Override
public void onLoadFailed(Exception e, Drawable errorDrawable)
{
}
#Override
public void onResourceReady(GlideDrawable resource, GlideAnimation<? super GlideDrawable> glideAnimation)
{
// GlideDrawable dr = resource;
Bitmap bitmap = ((com.bumptech.glide.load.resource.bitmap.GlideBitmapDrawable) resource).getBitmap();
String filename = doctorDetailsList.get(0).getDoc_imgurl().trim().substring(doctorDetailsList.get(0).getDoc_imgurl().trim().lastIndexOf("/") + 1);
filename = filename.replaceAll(".jpg", "");
int resID = getResources().getIdentifier(filename, "data", getPackageName());
Bitmap icon = BitmapFactory.decodeResource(mContext.getResources(), resID);
//Drawable d = new BitmapDrawable(getResources(), Bitmap.createScaledBitmap(bitmap, 200, 200, true));
RoundedBitmapDrawable circularBitmapDrawable = RoundedBitmapDrawableFactory.create(mContext.getResources(), icon);
circularBitmapDrawable.setCircular(true);
// GlideDrawable gd = new GlideDrawable(resource,)
getSupportActionBar().setLogo(circularBitmapDrawable);
}
#Override
public void onLoadCleared(Drawable placeholder)
{
}
#Override
public void getSize(SizeReadyCallback cb)
{
}
#Override
public void setRequest(com.bumptech.glide.request.Request request)
{
}
#Override
public com.bumptech.glide.request.Request getRequest()
{
return null;
}
#Override
public void onStart()
{
}
#Override
public void onStop()
{
}
#Override
public void onDestroy()
{
}
});
could not find a way, switched to Picasso and changed the code as following
Picasso.with(mContext)
.load(doctorDetailsList.get(0).getDoc_imgurl())
.resize(120, 120)
.centerCrop()
.placeholder(R.drawable.no_image)
.into(new com.squareup.picasso.Target()
{
#Override
public void onBitmapLoaded(Bitmap bitmap, Picasso.LoadedFrom from)
{
RoundedBitmapDrawable circularBitmapDrawable = RoundedBitmapDrawableFactory.create(mContext.getResources(), bitmap);
circularBitmapDrawable.setCircular(true);
getSupportActionBar().setLogo(circularBitmapDrawable);
}
#Override
public void onBitmapFailed(Drawable errorDrawable)
{
}
#Override
public void onPrepareLoad(Drawable placeHolderDrawable)
{
}
});
Has anyone used Glide to fetch images from a background thread? I keep getting this assert:
java.lang.IllegalArgumentException: You must call this method on the main thread
but according to this thread, it should work:
https://github.com/bumptech/glide/issues/310
Yet, I cannot get it to work, unless I call it from the main thread.
Here's is what I am trying to do from the main thread:
Glide.get(mContext);
loadUserImage(userImageUrl);
// wait 5 seconds before trying again
int imageLoadingTimeOut = mContext.getResources().getInteger(R.integer.image_loading_time_out);
if (imageLoadingTimeOut > 0) {
new Timer().schedule(new TimerTask() {
#Override
public void run() {
if (!mUserImageLoaded) {
loadUserImage(userImageUrl);
}
}
}, imageLoadingTimeOut);
}
}
and the loadUserImage:
private boolean mUserImageLoaded = false;
private void loadUserImage(String userImageUrl) {
if (userImageUrl != null && !userImageUrl.isEmpty() && !mUserImageLoaded) {
Glide.with(mContext).using(Cloudinary.getUrlLoader(mContext)).load(userImageUrl).crossFade().listener(new RequestListener<String, GlideDrawable>() {
#Override
public boolean onException(Exception e, String model, Target<GlideDrawable> target, boolean isFirstResource) {
return false;
}
#Override
public boolean onResourceReady(GlideDrawable resource, String model, Target<GlideDrawable> target, boolean isFromMemoryCache, boolean isFirstResource) {
mImageMessageContent.invalidate();
mUserImageLoaded = true;
return false;
}
}).into(mImageMessageContent);
} else {
mImageMessageContent.setVisibility(View.GONE);
}
}
and mContext is just the activity "this" pointer.
Anyway, can I use Glide from a thread different than main?
Update image in main ui thread
runOnUiThread(new Runnable() {
#Override
public void run() {
Glide.with(MainActivity.this)
.load("image URL")
.into(imageView);
}
});
The into(ImageView) method of Glide requires you to call it only on main thread, but when you pass the loading to a Timer it will be executed in a background thread.
What you can do is to retrieve a bitmap by calling get() instead of into() and then set that bitmap on the ImageView by calling setImageBitmap().
Glide.with(getApplicationContext())
.load("your url")
.asBitmap()
.into(new BitmapImageViewTarget(imgView) {
#Override
protected void setResource(Bitmap resource) {
//Play with bitmap
super.setResource(resource);
}
});
You can also take a look at this document for more information.
Posting the code just in case it helps someone.
Bitmap myBitmap = Glide.with(applicationContext)
.load(yourUrl)
.asBitmap()
.centerCrop()
.into(Target.SIZE_ORIGINAL,Target.SIZE_ORIGINAL)
.get()
imageView.setImageBitmap(myBitmap);
Here is the Kotlin-way solution
Glide.with(context).asBitmap().load(photo_url).into(
BitmapImageViewTarget(imgYourResourceID)
)
In my case i want to show notification from FirebaseMessagingService with image which will be downloaded via Glide, what gave me success is this piece of code:
try {
Bitmap bitmap= Glide.with(getApplicationContext())
.load(imageUrl) // image url in string
.asBitmap().into(Target.SIZE_ORIGINAL, Target.SIZE_ORIGINAL).get();
// now i can pass bitmap to notificationBuilder like
notificationBuilder.setStyle(new NotificationCompat.BigPictureStyle().bigPicture(bitmap));
} catch (InterruptedException e) {
e.printStackTrace();
} catch (ExecutionException e) {
e.printStackTrace();
}
I need to decrypt and display large images in a recyclerView
And because it was a heavy process, I had to do it in the background, so that's why :
public void decryptImage(Uri uri, ViewHolder holder) {
Runnable runnable = new Runnable() {
#Override
public void run() {
try {
Glide.with(G.context)
.asBitmap()
.load(decrypt(G.getEncryptionKey(), G.getConstantKey(), uri.getPath()))
.into(new SimpleTarget<Bitmap>() {
#Override
public void onResourceReady(Bitmap resource, Transition<? super Bitmap> transition) {
Glide.with(G.context).load(resource).into(holder.mImageView);
}
});
}
};
new Thread(runnable).start();
}
private class AsyncTaskRunner extends AsyncTask<String, String, RequestBuilder>
{
ProgressDialog progressDialog;
#Override
protected void onPreExecute() {
progressDialog = ProgressDialog.show(MainActivity.this,
"Please Wait",
"Image is loading...");
}
#Override
protected RequestBuilder<Drawable> doInBackground(String... strings) {
URL url = null;
try {
url = new URL(strings[0]);
} catch (MalformedURLException e) {
e.printStackTrace();
}
RequestBuilder<Drawable> g= Glide.with(MainActivity.this).load(url);
return g;
}
#Override
protected void onPostExecute(RequestBuilder v) {
v.into(imageView);
imageView.setVisibility(View.VISIBLE);
progressDialog.dismiss();
}
}
I am trying to load an image:
Picasso.with(SelectActivity.this).load(picture).into(new Target() {
#Override
public void onBitmapLoaded(Bitmap bitmap, Picasso.LoadedFrom from) {
bmp = bitmap;
findViewById(R.id.facebookButton).setEnabled(true);
continueToEditing();
}
#Override
public void onBitmapFailed(Drawable errorDrawable) {
findViewById(R.id.facebookButton).setEnabled(true);
}
#Override
public void onPrepareLoad(Drawable placeHolderDrawable) {
}
});
picture is a valid string to a reachable, valid JPEG image. I've got everything inside a try/catch block and I've got breakpoints on onBitmapLoaded, onBitmapFailed, and try/catch's catch block.
However, none of this is called. There is also nothing in logcat related to this, too. What am I doing wrong?
Try keeping a strong reference to the Target object as a class variable and give it a try.
E.g.
Target target;// Class variable
//Now define this on your onCreate method
target = new Target() {
#Override
public void onBitmapLoaded(Bitmap bitmap, Picasso.LoadedFrom from) {
bmp = bitmap;
findViewById(R.id.facebookButton).setEnabled(true);
continueToEditing();
}
#Override
public void onBitmapFailed(Drawable errorDrawable) {
findViewById(R.id.facebookButton).setEnabled(true);
}
#Override
public void onPrepareLoad(Drawable placeHolderDrawable) {
}
});
//Now set the target on the Piccaso load LOC
Picasso.with(SelectActivity.this).load(picture).into(target);
I'm using Picasso to download images for my app.
I'm in a situation where I need to access the Bitmap first before it's loaded into the ImageView. The presence of the Downloader.Response class seems to suggest this is possible, but I can't find any use examples. I don't want to write a bunch more code to asynchronously handle this one particular case if it's possible to do with Picasso.
Can anyone show me how to do it?
Found the answer on github in case anyone is wondering:
private Target target = new Target() {
#Override
public void onBitmapLoaded(Bitmap bitmap, Picasso.LoadedFrom from) {
}
#Override
public void onBitmapFailed(Drawable errorDrawable) {
}
#Override
public void onPrepareLoad(Drawable placeHolderDrawable) {
}
}
private void someMethod() {
Picasso.with(this).load("url").into(target);
}
#Override
public void onDestroy() { // could be in onPause or onStop
Picasso.with(this).cancelRequest(target);
super.onDestroy();
}
The post recommends not using an anonymous callback, and instead using an instance variable for target.
taken from here:
Picasso.with(this)
.load(url)
.into(new Target() {
#Override
public void onBitmapLoaded (final Bitmap bitmap, Picasso.LoadedFrom from){
/* Save the bitmap or do something with it here */
//Set it in the ImageView
theView.setImageBitmap(bitmap);
}
});
Updated (May 04, 2016):
Picasso.with(this)
.load(youUrl)
.into(new Target() {
#Override
public void onBitmapLoaded(Bitmap bitmap, Picasso.LoadedFrom from) {
}
#Override
public void onBitmapFailed(Drawable errorDrawable) {
}
#Override
public void onPrepareLoad(Drawable placeHolderDrawable) {
}
});
Updated (November 22, 2016)
or using a strong reference for Target so that it wont be garbage collected
Target target = new Target() {
#Override
public void onBitmapLoaded(Bitmap bitmap, Picasso.LoadedFrom from) {
}
#Override
public void onBitmapFailed(Drawable errorDrawable) {
}
#Override
public void onPrepareLoad(Drawable placeHolderDrawable) {
}
};
void foo() {
Picasso.with(getContext()).load(getUrl()).into(target);
}
Kotlin
object: com.squareup.picasso.Target {
override fun onBitmapFailed(e: java.lang.Exception?, errorDrawable: Drawable?) {
TODO("not implemented") //To change body of created functions use File | Settings | File Templates.
}
override fun onPrepareLoad(placeHolderDrawable: Drawable?) {
TODO("not implemented") //To change body of created functions use File | Settings | File Templates.
}
override fun onBitmapLoaded(bitmap: Bitmap?, from: Picasso.LoadedFrom?) {
}
}
What can be easy than next:
val url: String = "https://...."
val bitmap: Bitmap = Picasso.with(context).load(url).get()
Should be called from not the main thread!
or with RxJava 2:
fun getBitmapSingle(picasso: Picasso, url: String): Single<Bitmap> = Single.create {
try {
if (!it.isDisposed) {
val bitmap: Bitmap = picasso.load(url).get()
it.onSuccess(bitmap)
}
} catch (e: Throwable) {
it.onError(e)
}
}
Retrieve Bitmap:
getBitmapSingle(Picasso.with(context), "https:/...")
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe({ bitmap ->
// val drawable = BitmapDrawable(context, bitmap)
}, Throwable::printStackTrace)
I used Picasso v.2.5.2
I thought maybe some of you would like an RxJava version of the above answer... Here it is:
public static Observable<Bitmap> loadBitmap(Picasso picasso, String imageUrl) {
return Observable.create(new Observable.OnSubscribe<Bitmap>() {
#Override
public void call(Subscriber<? super Bitmap> subscriber) {
Target target = new Target() {
#Override
public void onBitmapLoaded(Bitmap bitmap, Picasso.LoadedFrom from) {
subscriber.onNext(bitmap);
subscriber.onCompleted();
}
#Override
public void onBitmapFailed(Drawable errorDrawable) {
subscriber.onError(new Exception("failed to load " + imageUrl));
}
#Override
public void onPrepareLoad(Drawable placeHolderDrawable) {
}
};
subscriber.add(new Subscription() {
private boolean unSubscribed;
#Override
public void unsubscribe() {
picasso.cancelRequest(target);
unSubscribed = true;
}
#Override
public boolean isUnsubscribed() {
return unSubscribed;
}
});
picasso.load(imageUrl).into(target);
}
});
}
P.S. When subscribing, store the subscription reference on your activity, otherwise, target will be GC'd before you receive a response...