I have a big problem with loading images from cache on the getView of my Listadapter.
For image-loading we are using Picasso, and there I build a construct for loading images from cache and if there are no available images, THEN the images should be load from an online-URI.
(Here is a method, which is called inside of my getView of my Adapter)
#Override
protected void loadImages(final VehicleResultListItem inCurrentItem) {
// Try to load async the images from local path
Picasso.with(mContext)
.load(new File(mContext.getExternalFilesDir(null),
inCurrentItem.getVehicleId()))
.placeholder(inCurrentItem.getServiceType().getPlaceholderId())
.noFade()
.into(new Target() {
#Override
public void onBitmapLoaded(final Bitmap bitmap,
final Picasso.LoadedFrom from) {
mThumbnailImgView.setImageBitmap(bitmap);
}
#Override
public void onBitmapFailed(final Drawable errorDrawable) {
// If the local-path-loading fails, try to grab the images online.
Picasso.with(mContext)
.load(inCurrentItem.getImageURIs().get(0).getImageUriSizeM())
.placeholder(inCurrentItem.getServiceType().getPlaceholderId())
.into(new Target() {
#Override
public void onBitmapLoaded(final Bitmap bitmap,
final Picasso.LoadedFrom from) {
// On succesfully online-loading of the images, store and show them
mThumbnailImgView.setImageBitmap(bitmap);
saveToInternalSorage(bitmap, inCurrentItem);
}
#Override
public void onBitmapFailed(final Drawable errorDrawable) {
// NO interaction
}
#Override
public void onPrepareLoad(final Drawable placeHolderDrawable) {
// No interaction
}
});
}
#Override
public void onPrepareLoad(final Drawable placeHolderDrawable) {
mThumbnailImgView.setImageDrawable(placeHolderDrawable);
}
});
}
The problem is, that the image is loading correctly, but the imageView is not updating after image is loaded. In the OnImageLoaded, I am not in the UI-Thread, so ofc it does not update the view. So i tried anything:
Runnable
AsyncTask
Androids solution from (http://developer.android.com/training/displaying-bitmaps/process-bitmap.html#concurrency)
It looks like the Threads are getting confused or something like that.
Maybe there is a problem in calling Picasso inside of a Picasso-Target?
Do u have any suggestion?
Greetz and thx
Target must not be an anonymous class. Picasso keeps a WeakReference on Target that will most likely get gc'ed by the time the request completes.
Javadoc clearly states that.
Make your View implement Target instead and use that as the target or keep a reference to your target instances.
Also Picasso handles disk caching for you automatically, unless you've shipped the assets with your app, I would recommend you simply download them and then let Picasso manage the disk/memory cache for you.
Related
I'm using StickerView to add stickers to my app, now I'm trying to add GIF drawable as a sticker, the below code works, the GifDrawable is animated normally, but the issue here is each time the Drawable changes to the next frame, the entire StickerView is redrawn, over and over again, this consumes quite a bit of memory.
I tried to invalidate the drawable only using stickerView.invalidateDrawable(who), but GifDrawable stops animating.
GifDrawable gifDrawable = new GifDrawable(gifSticker.getBuffer());
gifDrawableSticker.setGIF(true);
gifDrawable.setCallback(new Drawable.Callback() {
#Override
public void invalidateDrawable(#NonNull Drawable who) {
stickerView.invalidate(); WORKING FINE
//stickerView.invalidateDrawable(who); NOT WORKING
}
#Override
public void scheduleDrawable(#NonNull Drawable who, #NonNull Runnable what, long when) {
stickerView.scheduleDrawable(who, what, when);
}
#Override
public void unscheduleDrawable(#NonNull Drawable who, #NonNull Runnable what) {
stickerView.unscheduleDrawable(who, what);
}
});
stickerView.addSticker(new DrawableSticker(gifDrawable));
I wrote the following code:
Glide.with(this).asBitmap().load(userImageURL).into(new CustomViewTarget<ImageView, Bitmap>(userAvatarImage) {
#Override
protected void onResourceCleared(#Nullable Drawable placeholder) {
progressBarUserAvatar.setVisibility(View.GONE);
userAvatarImage.setImageBitmap(null);
}
#Override
public void onLoadFailed(#Nullable Drawable errorDrawable) {
progressBarUserAvatar.setVisibility(View.GONE);
final Bitmap circleLetterTile = tileProvider.getCircularLetterTile(userFullName);
userAvatarImage.setImageBitmap(circleLetterTile);
}
#Override
public void onResourceReady(#NonNull Bitmap resource, #Nullable Transition<? super Bitmap> transition) {
progressBarUserAvatar.setVisibility(View.GONE);
final Bitmap circleAvatarBitmap = tileProvider.getCircularImage(resource);
userAvatarImage.setImageBitmap(circleAvatarBitmap);
userAvatarImage.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
Intent showProfilePictureIntent = new Intent(UserProfileActivity.this, DisplayUserImageActivity.class);
showProfilePictureIntent.putExtra("userImageURL",userImageURL);
final String transitionName = ViewCompat.getTransitionName(userAvatarImage);
ActivityOptionsCompat options = ActivityOptionsCompat.makeSceneTransitionAnimation(
UserProfileActivity.this, userAvatarImage, transitionName);
UserProfileActivity.this.startActivity(showProfilePictureIntent, options.toBundle());
UserProfileActivity.this.overridePendingTransition(R.anim.fade_in, R.anim.fade_out);
}
});
}
});
It basically displays the user's image using Glide. It also set a onClick listener that opens the image in large mode with black background. Currently, UserProfileActivity is empty (just loads the layout). The problem is that I can't use getTransitionName because it's possible only for api 21. I'm have to use API 16 in my project so it's a problem. What would be the easiest way to achieve it? I looked into previous topics but they all between 2013-2015 so I thought maybe there is a way to do it.
This is not possible to do, using API >21. As you can refer to the official documentation here https://developer.android.com/reference/android/app/ActivityOptions#makeSceneTransitionAnimation(android.app.Activity,%20android.view.View,%20java.lang.String).
I'm not sure, why you don't have warning usage, but do for getTransitionName. Unfortunately it's not supported on early version. As another reference you can check https://www.programcreek.com/java-api-examples/?class=android.app.ActivityOptions&method=makeSceneTransitionAnimation about examples how to use transition animation.
Off topic
You can achieve animation you want by writing own tools with transition animation. It's not so easy, but it's pure view implementation, and you don't need new Android version. For the same reason, you can use Flutter (min version for which is Android 16) and make transition animation (hero animation) with few lines of codes. Because it's out of box implementation.
I'm making an app that in many other functions, pulls images via URL and then it shows them in a PDF file. I did it on the hard way downloading them and using an asyncTask to handle all the process, but I heard that piccasso does this work better and cleaner so I decided to give it a try.
So I want to put the image loaded with piccaso within a Drawable so let's say I'm trying to do something like this:
Drawable drawable=Picasso.get().load("URL");
which of course is ridiculous and it's impossible, so I'm wondering if there is a way I can pull the image
with picasso and then transform it to a Drawable so I can then draw it on the PDF file that I need to generate
This code may help you:
Target target = new Target() {
#Override
public void onBitmapLoaded(Bitmap bitmap, Picasso.LoadedFrom from) {
imageView.setImageBitmap(bitmap);
Drawable image = imageView.getDrawable();
}
#Override
public void onBitmapFailed(Drawable errorDrawable) {}
#Override
public void onPrepareLoad(Drawable placeHolderDrawable) {}
};
Picasso.with(this).load("url").into(target);
Or, just look here: https://stackoverflow.com/a/25799983/11162243
I am using picasso inside my recyclerview adapter for loading images from network. I've tested it with 40+ items in my recyclerview and 29 of them have images.
I noticed that upon reaching the end of list, when I scroll back up, some of the images are being reloaded from network instead of cache. Is there any way to prevent reloading the image again from the network? Or perhaps an alternative for reducing network bandwidth usage.
Picasso.with(context)
.load(HOST + post.getImage_url())
.resize(1920, 1080)
.onlyScaleDown()
.networkPolicy(NetworkPolicy.OFFLINE)
.into(holder.ivPostImage, new Callback() {
#Override
public void onSuccess() {
}
#Override
public void onError() {
Picasso.with(context)
.load(HOST + post.getImage_url())
.resize(1920, 1080)
.onlyScaleDown()
.into(holder.ivPostImage);
}
});
Above is the code that I use for caching images loaded from the network.
I'm attempting parse a JSON payload and place the information in Relative Layout View.
I use this STANDARD asynchronous download routine to obtain the bitmaps to be placed in the appropriate ImageView:
public class AsyncDownloadImage extends AsyncTask<String,Void,Bitmap>{
ImageView bmImage;
public AsyncDownloadImage(ImageView bmImage){
this.bmImage = bmImage;
}
#Override
protected Bitmap doInBackground(String... urls) {
String urldisplay = null;
urldisplay = urls[0];
Bitmap merchViewBitMap = Bitmap.createBitmap(90,90,Bitmap.Config.ARGB_8888);
try{
InputStream in = new URL(urldisplay).openStream();
merchViewBitMap = BitmapFactory.decodeStream(in);
in.close();
}catch(Exception e){
System.out.println(String.format("Image Download Exception ==> %s", e.toString()));
}
return merchViewBitMap;
}
#Override
protected void onPostExecute(Bitmap result) {
super.onPostExecute(result);
bmImage.setImageBitmap(result);
}
}
It's called this way in the getView method of the Adapter class:
String imageUrl = String.format("https://www.xxxxxx.com/va/public/render_image?image_id=%s", currentMerchItem.getMt_image_id());
new AsyncDownloadImage(viewHolder.imageview).execute(imageUrl);
The images are downloaded and the ImageView(s) are set, but they are downloaded repeatedly and infinitely. Multiple images seem to be in an ImageView and when scrolled through they change as each is gif.
How do I stop this after the last image in the list is downloaded?!
-TU
The adapters getView method will be called each time the view of the adapter (listview for example) needs to refresh item's view. When you scroll for example you will get many calls to the getview method (depends on the list length ofcourse). At least you need to manage which images are already being loaded from the net in your case. You also have a lot of open source code for lazy loading exactly for cases like yours.
You can also check this thread, it may help you:
Lazy load of images in ListView