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.
Related
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.
Good day.I have an google map with cluster manager.Simple one,where i use the cluster to draw markers grouped or not.Anyway i got an method callback from cluster manager which is the Cluster item render one.Inside that callback i am applying custom image to the marker:The user image inside marker.I found Picasso to be the best to handle bitmap loading and at the same time got me lots of headache.I am using Target class from Picasso to initiate the bitmap callbacks:OnPreLoad,OnFail,OnBitmapLoaded.The issue is that on first cluster item render the onBitmapLoaded not called and generally it is never gets called unless it has been touched second time.On first time nothing happens,no callback is triggered except OnPreLoad and by googling i found that the great Picasso holds weak reference to the class.I tried all the examples of the google:Making Target reference strong(getting the initialazation of class out of method and init the class inside my class like the follows)
#Override
protected void onClusterItemRendered(MarkerItem clusterItem, Marker marker) {
mMarker = marker;
mMarkerItem = clusterItem;
Picasso.with(mContext).load(clusterItem.getImageUrl()).transform(new CircleTransformation()).into(target);
}
private Target target = new Target() {
#Override
public void onBitmapLoaded(Bitmap bitmap, Picasso.LoadedFrom from) {
Log.d(TAG, "onBitmapLoaded: ");
}
#Override
public void onBitmapFailed(Drawable errorDrawable) {
Log.d(TAG, "onBitmapFailed: ");
}
#Override
public void onPrepareLoad(Drawable placeHolderDrawable) {
Log.d(TAG, "onPrepareLoad: ");
}
};
#Override
protected void onBeforeClusterItemRendered(MarkerItem item, MarkerOptions markerOptions) {
markerOptions.title(item.getTitle());
markerOptions.icon(item.getIcon());
}
At this point i get the same result....Sometimes the bitmap loaded and sometimes not.Mostly not...
Anyway i have tried to implement the interface class to my own class as follows:
public class PicassoMarkerView implements com.squareup.picasso.Target {
private static final String TAG = "MarkerRender";
private Bitmap mMarkerBitmap;
private ClusterManager<MarkerItem> mClusterManager;
private MarkerItem mMarkerItem;
private Marker mMarker;
public PicassoMarkerView() {
}
#Override
public int hashCode() {
return mMarker.hashCode();
}
#Override
public boolean equals(Object o) {
if (o instanceof PicassoMarkerView) {
Marker marker = ((PicassoMarkerView) o).mMarker;
return mMarker.equals(marker);
} else {
return false;
}
}
#Override
public void onBitmapLoaded(Bitmap bitmap, Picasso.LoadedFrom from) {
Bitmap scaledBitmap = Bitmap.createScaledBitmap(bitmap,
mMarkerBitmap.getWidth() - 15, (int) (mMarkerBitmap.getHeight() / 1.5 - 15),
false);
mMarker.setIcon(BitmapDescriptorFactory.fromBitmap(overlay(mMarkerBitmap, scaledBitmap, 8, 7)));
Log.d(TAG, "onBitmapLoaded: ");
}
#Override
public void onBitmapFailed(Drawable errorDrawable) {
Log.d(TAG, "onBitmapFailed: ");
}
#Override
public void onPrepareLoad(Drawable placeHolderDrawable) {
Log.d(TAG, "onPrepareLoad: ");
}
private Bitmap overlay(Bitmap bitmap1, Bitmap bitmap2, int left, int top) {
Bitmap res = Bitmap.createBitmap(bitmap1.getWidth(), bitmap1.getHeight(),
bitmap1.getConfig());
Canvas canvas = new Canvas(res);
canvas.drawBitmap(bitmap1, new Matrix(), null);
canvas.drawBitmap(bitmap2, left, top, null);
return res;
}
public void setMarkerBitmap(Bitmap markerBitmap) {
this.mMarkerBitmap = markerBitmap;
}
public void setClusterManager(ClusterManager<MarkerItem> clusterManager) {
this.mClusterManager = clusterManager;
}
public void setMarkerItem(MarkerItem markerItem) {
this.mMarkerItem = markerItem;
}
public void setMarker(Marker marker) {
this.mMarker = marker;
}
}
Unfortunatally this is not working either...Same result...So please dear friends can you give me an working example of this?As far as i could google,the issue mostly happens to the user which try to do this inside loop and my onClusterItemRender some sort of loop lets say as it is triggered every time marker is visible to user,so yeah it is triggered several times and as fast as loop so give me some idea please and help me out...
Important to mention that i do not need to use methods from picasso like fetch(),get() as they are not necessary and not fitting the purpose of the app.
I encountered similar issue and holding reference to the target didn't help at all.
The purpose of my project was to use 2 different image downloading api's to show an images gallery and to give the user the ability to choose which api to use.
Beside Picasso I used Glide, and I was amazed by the results, Glide's api worked flawlessly in every aspect wile Picasso gave me hell (that was my first time using Glide, I usually used Picasso so far, seems like today it's gonna change ^^ ).
So my suggestion to you is:
Use glide over Picasso (no such weak reference on their target).
Since I had to use both libraries I ended up using get() in an handler, not sure if it will help you but it solved my problem:
handlerThread = new HandlerThread(HANDLER_THREAD_NAME);
handlerThread.start();
Handler handler = new Handler(handlerThread.getLooper());
handler.post(new Runnable() {
#Override
public void run() {
Bitmap bitmap = null;
try {
bitmap = picasso.with(appContext).load(url).get();
} catch (IOException e) {
e.printStackTrace();
}finally {
if (bitmap != null) {
//do whatever you wanna do with the picture.
//for me it was using my own cache
imageCaching.cacheImage(imageId, 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));
I am trying to pass a URL to be converted to a bitmap to be used in the activity. I have a class of "Projects" and everything loads fine from the API, including the String Url for the image.
My code looks like this:
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_discover);
ButterKnife.bind(this);
Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
setSupportActionBar(toolbar);
target = new Target() {
#Override
public void onBitmapLoaded(Bitmap bitmap, Picasso.LoadedFrom from) {
adapter.add(new CardModel(mProject.mName, mProject.mTagline, bitmap));
}
#Override
public void onBitmapFailed(Drawable errorDrawable) {
}
#Override
public void onPrepareLoad(Drawable placeHolderDrawable) {
Log.d("ISSUE:: ", "IMAGE NOT LOADED");
}
};
adapter = new SimpleCardStackAdapter(this);
mController = new Controller(this);
mController.startFetchingProjects();
}
#Override
public void onFetchProgress(Project project) {
mProjectList.add(project);
mImageUrls.add(project.mImageUrl);
}
#Override
public void onFetchComplete() {
for (int i = 0; i < mProjectList.size(); i++){
mProject = mProjectList.get(i);
mImage = mImageUrls.get(i);
Picasso.with(this).load(mImage).into(target);
}
}
}
For some reason even though there are 24 projects, when I try to load an image, it returns only about 8 random images (the rest go through onPrepareLoad for some reason). If I adapt my projects with no images, I'll have 24 projects, but when I include this picasso method, I only get about 8 images returned, and thus only 8 projects returned. Any idea how to fix this?
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);
}
}