Issues with loading bitmaps with Picasso library in onPostExecute() - android

I've got a problem loading bitmaps with Picasso in a loop. I'm loading them in AsyncTasks onPostExecute(). I know that i need global Target variables to prevent them from being collected by GC. Still none of my bitmaps are loaded. Here's my code:
private static Map<Integer, Bitmap> markerBitmaps;
private String[] markerUrls;
private Integer[] catIds;
//some code
private final static List<Target> targets = new ArrayList<Target>();
#Override
protected void onPostExecute(Void result) {
final int[] id = new int[1];
int counter = 0;
for(String s : markerUrls) {
id[0] = catIds[counter];
Target target = new Target() {
#Override
public void onBitmapLoaded(Bitmap bitmap, Picasso.LoadedFrom from) {
targets.remove(this);
markerBitmaps.put(id[0], bitmap);
}
#Override
public void onBitmapFailed(Drawable errorDrawable) {
targets.remove(this);
}
#Override
public void onPrepareLoad(Drawable placeHolderDrawable) {
}
};
Log.i("BITMAP URL IS:", s);
targets.add(target);
Picasso.with(MapsMenuActivity.this)
.load(s)// Start loading the current target
.into(target);
counter++;
}
Log.i("BITMAPS NUM: ", String.valueOf(markerBitmaps.size()));
}
The size of my markerBitmaps map is always 0.

Related

Downloading two images at the same time with Picasso and using Target. But doesn't finish and load image

So I'm downloading two images using Picasso at the same time, as follows:
Picasso.with(this).load(Constants.SERVER_HOME_PAGE_TOP_IMAGE_URL).into(new Target() {
#Override
public void onBitmapLoaded(Bitmap bitmap, Picasso.LoadedFrom from) {
sLastBitmapLoadedDate = Calendar.getInstance();
int h= (int) (Constants.PAGE_TOP_IMAGE_HEIGHT * densityMultiplier);
int w= (int) (h * bitmap.getWidth()/((double) bitmap.getHeight()));
sTipBitmap = Bitmap.createScaledBitmap(bitmap, w, h, true);
Log.v("Image: ", "one");
topImage.setImageBitmap(sTipBitmap);
}
#Override
public void onBitmapFailed(Drawable errorDrawable) {
}
#Override
public void onPrepareLoad(Drawable placeHolderDrawable) {
}
});
Picasso.with(this).load(Constants.SERVER_HOME_PAGE_BOTTOM_IMAGE_URL).into(new Target() {
#Override
public void onBitmapLoaded(Bitmap bitmap, Picasso.LoadedFrom from) {
sLastBitmapLoadedDate = Calendar.getInstance();
int h= (int) (Constants.PAGE_BOTTOM_IMAGE_HEIGHT * densityMultiplier);
int w= (int) (h * bitmap.getWidth()/((double) bitmap.getHeight()));
sAdBitmap = Bitmap.createScaledBitmap(bitmap, w, h, true);
Log.v("Image: ", "two");
bottomImage.setImageBitmap(sAdBitmap);
}
#Override
public void onBitmapFailed(Drawable errorDrawable) {
}
#Override
public void onPrepareLoad(Drawable placeHolderDrawable) {
}
});
I'm modifying the image size by using Target. So I never hit the onBitMapLoaded on both cases. If i comment out one of the requests, then it will load the image and hit the onBitMapLoaded, where i resize the image.
So I'm for sure going about this the wrong way. If someone could help me out and explain what I am doing wrong.
Thanks!
I've been there. Tried over 3 days to download multiple images using Picasso. However I found that the best way to download multiple images is to use a file downloader library. The FileDownloader library is an incredible choice as it allows to download multiple images in a queue both synchronously and asynchronously.
As a snapshot, this is how you'd download multiple images as a queue using this library:
final FileDownloadListener queueTarget = new FileDownloadListener() {
#Override
protected void pending(BaseDownloadTask task, int soFarBytes, int totalBytes) {
}
#Override
protected void connected(BaseDownloadTask task, String etag, boolean isContinue, int soFarBytes, int totalBytes) {
}
#Override
protected void progress(BaseDownloadTask task, int soFarBytes, int totalBytes) {
}
#Override
protected void blockComplete(BaseDownloadTask task) {
}
#Override
protected void retry(final BaseDownloadTask task, final Throwable ex, final int retryingTimes, final int soFarBytes) {
}
#Override
protected void completed(BaseDownloadTask task) {
}
#Override
protected void paused(BaseDownloadTask task, int soFarBytes, int totalBytes) {
}
#Override
protected void error(BaseDownloadTask task, Throwable e) {
}
#Override
protected void warn(BaseDownloadTask task) {
}
};
final FileDownloadQueueSet queueSet = new FileDownloadQueueSet(downloadListener);
final List<BaseDownloadTask> tasks = new ArrayList<>();
for (int i = 0; i < count; i++) {
tasks.add(FileDownloader.getImpl().create(Constant.URLS[i]).setTag(i + 1));
}
queueSet.disableCallbackProgressTimes(); // Do not need for each task callback `FileDownloadListener#progress`,
// We just consider which task will complete. so in this way reduce ipc will be effective optimization.
// Each task will auto retry 1 time if download fail.
queueSet.setAutoRetryTimes(1);
if (serial) {
// Start downloading in serial order.
queueSet.downloadSequentially(tasks);
// If your tasks are not a list, invoke such following will more readable:
// queueSet.downloadSequentially(
// FileDownloader.getImpl().create(url).setPath(...),
// FileDownloader.getImpl().create(url).addHeader(...,...),
// FileDownloader.getImpl().create(url).setPath(...)
// );
}
if (parallel) {
// Start parallel download.
queueSet.downloadTogether(tasks);
// If your tasks are not a list, invoke such following will more readable:
// queueSet.downloadTogether(
// FileDownloader.getImpl().create(url).setPath(...),
// FileDownloader.getImpl().create(url).setPath(...),
// FileDownloader.getImpl().create(url).setSyncCallback(true)
// );
}
queueSet.start();
The entire usage guide is available here : Wiki
Also, This is the question I've had asked in order to download multiple images using Picasso : Downloading images using Picasso creates incorrect images in cache, possible fix?

How to clear images loaded by Picasso on Android?

I have a BackgroundImageActivity that load background image using Picasso. But when I go back to home (onStop() called in BackgroundImageActivity) and go into another instance of this activity, which is supposed to load another background image, but at first 2 seconds, it still shows the image from previous BackgroundImageActivity. Is this some kind of cache?
How I can clear this image so that whenever I go into a new instance of BackgroundImageActivity, i don't see the image from previous one?
public class BackgroundImageActivity extends Activity {
#Override
public void onCreate(final Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
initBackground();
}
#Override
protected void onStop() {
super.onStop();
Picasso.invalidate(imageUrl, getApplicationContext());
}
private void initBackground() {
...
}
private void setBg(final String imageUrl, final int bg) {
this.imageUrl = imageUrl;
final RequestCreator picassoRequest = Picasso.load(imageUrl, bg).memoryPolicy(MemoryPolicy.NO_CACHE);
targetReference = new Target() {
#Override
public void onBitmapLoaded(final Bitmap bitmap, final Picasso.LoadedFrom from) {
...
}
#Override
public void onBitmapFailed(final Drawable errorDrawable) {
...
}
#Override
public void onPrepareLoad(final Drawable placeHolderDrawable) {
...
}
};
picassoRequest.placeholder(bg).error(bg).into(targetReference);
}
}
Thanks!!!
Use this piece of code while loading the image.
Picasso.with(getContext())
.load(data.get(pos)
.getFeed_thumb_image())
.memoryPolicy(MemoryPolicy.NO_CACHE)
.into(image);
Picasso set the image to ImageView directly without caching in the background. This makes the app lightweight also.

How to check that all the files uploaded by Picasso lib?

I want before render MainActivity check what all pictures is loaded:
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
...
getBitmapsByURLs(urls);
}
public void getBitmapsByURLs(List<String> urls) {
final List<Target> targets = new ArrayList<>();
for (int i = 0; i < urls.size(); i++) {
final int k = i;
Target target = new Target() {
#Override
public void onBitmapLoaded(Bitmap bitmap, Picasso.LoadedFrom from) {
Log.i("TEMP", "Loaded: " + k);
targets.remove(this);
}
#Override
public void onBitmapFailed(Drawable errorDrawable) {
targets.remove(this);
}
#Override
public void onPrepareLoad(Drawable placeHolderDrawable) {
Log.i("TEMP", "Preparing: " + k);
}
};
targets.add(target);
Picasso.with(this)
.load(urls.get(i))
.memoryPolicy(NO_CACHE, NO_STORE)
.into(target);
}
}
How I can check inside onCreate what all pictures is loaded?
If I write while on method onCreate (after call getBitmapsByURLs) then it will be called before all pictures are loaded.
You must be known that when you use
Picasso.with(this)
.load(urls.get(i))
.memoryPolicy(NO_CACHE, NO_STORE)
.into(target);
to load a picture,it is a asynchronized task.First picasso download the picture from internet.After downloading is finished,the picture will be loaded into target.Of course,when downloading,the main thread will never be waiting.Picasso use something like Observer-Subcriber or interface Future to make the main thread informed that downing is over.Above all,no matter what you write after getBitmapsByURLs(urls),it will be called before picasso finishes loading pictures.(Because it usually costs some more time to download pictures and load them into targets).
What's more.This is not a recommended way to do such a time-costing work in onCreate().Because onCreate() is called in main thread.If you do something costs much time here,then you will get an Application Not Responding error.

IntentService Terminated before Picasso loads Bitmap

I'm trying to use an IntentService for processing and uploading images that's running in a different process to have more memory. I'm Using also Picasso to load the Image. When the Image is small the bitmap is loaded successfully and uploaded, however if the image is big the IntentService is terminated before Picasso is done loading It.
Picasso have to run on UIThread
Here is the code.
private void downloadImage(File file) {
final Uri uri = Uri.fromFile(file);
Handler uiHandler = new Handler(Looper.getMainLooper());
uiHandler.post(new Runnable() {
#Override
public void run() {
Picasso.with(NewImageProcessingService.this).load(uri).transform(new ImageLoadingUtil.DecreaseQualityTransformation(imageQuality)).into(NewImageProcessingService.this);
}
});
}
#Override
protected void onHandleIntent(Intent intent) {
File file = (File) intent.getSerializableExtra(KEY_IMAGE_FILE);
imageQuality = ImagesUtils.IMAGE_QUALITY
.values()[intent.getIntExtra(IMAGE_QUALITY, ImagesUtils.IMAGE_QUALITY.DEFAULT.ordinal())];
downloadImage(file);
}
This question is quite old, but if anyone steps by. The Target is getting garbage collected before it can show the bitmap.
Use it like this
public class BitmapLoader {
public static Target getViewTarget(final OnImageLoadingCompleted onCompleted) {
return new Target() {
#Override
public void onBitmapLoaded(Bitmap bitmap, Picasso.LoadedFrom from) {
onCompleted.imageLoadingCompleted(bitmap);
}
#Override
public void onBitmapFailed(Drawable errorDrawable) {
}
#Override
public void onPrepareLoad(Drawable placeHolderDrawable) {
}
};
}
}
You need to have a strong reference to the Target so have a field in your IntentService holding it e.g.
private Target viewTarget;
viewTarget = BitmapLoader.getViewTarget(bitmap -> {
// do stuff with the bitmap
});
new Handler(Looper.getMainLooper()).post(() -> Picasso.with(getApplicationContext()).load(object.getImageUrl()).into(viewTarget));

Picasso - how to fetch image sequentially

I wanna retrieve images in Picasso for later and keep them in cache, at the moment I use this code:
for(int i=0; i<urlList.size(); i++) {
Picasso.with(getActivity())
.load(url.get(i))
.fetch();
}
but I wanna retrieve them sequentially. What's the best for that?
You can load the image into a Target, if you have an array of your urls you can recursively load them from the Target.
Example activity that does this:
public class MainActivity extends ActionBarActivity{
private ArrayList<String> urls;
#Override
protected void onCreate(Bundle savedInstanceState){
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
urls = new ArrayList<>();
urls.add("http://placehold.it/300&text=0");
urls.add("http://placehold.it/300&text=1");
urls.add("http://placehold.it/300&text=2");
urls.add("http://placehold.it/300&text=3");
urls.add("http://placehold.it/300&text=4");
loadImages(0);
}
private void loadImages(final int index){
Target t = new Target(){
#Override
public void onBitmapLoaded(Bitmap bitmap, Picasso.LoadedFrom from){
Log.w("image", "image received" + index);
loadImages(index + 1);
}
#Override
public void onBitmapFailed(Drawable errorDrawable){
}
#Override
public void onPrepareLoad(Drawable placeHolderDrawable){
}
};
if(index < urls.size())
Picasso.with(this)
.load(urls.get(index))
.into(t);
}
}

Categories

Resources