Use Picasso to get a callback with a Bitmap
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.
get bitmap image using picasso library
You can implement your own class implementing the Target interface and then call:
Picasso.with(context).load("file:///android_asset/DvpvklR.png").into(target);
How to load a Bitmap with Picasso without using an ImageView?
You can create a Target
and then modify the Bitmap
inside the Targets callback method onBitmapLoaded(...)
. Here is how:
// make sure to set Target as strong reference
private Target loadtarget;
public void loadBitmap(String url) {
if (loadtarget == null) loadtarget = new Target() {
@Override
public void onBitmapLoaded(Bitmap bitmap, Picasso.LoadedFrom from) {
// do something with the Bitmap
handleLoadedBitmap(bitmap);
}
@Override
public void onBitmapFailed() {
}
};
Picasso.with(this).load(url).into(loadtarget);
}
public void handleLoadedBitmap(Bitmap b) {
// do something here
}
Get Bitmap using a Target in Picasso
This code is working for me:
...
private static final String TAG = MainActivity.class.getName();
private Target mTarget;
...
mTarget = new Target() {
@Override
public void onBitmapLoaded(Bitmap bitmap, Picasso.LoadedFrom from) {
if (bitmap == null) {
Log.w(TAG, "Null");
} else {
Log.i(TAG, "Worked");
}
}
@Override
public void onBitmapFailed(Exception e, Drawable errorDrawable) {
Log.w(TAG, "failed");
}
@Override
public void onPrepareLoad(Drawable placeHolderDrawable) {
Log.i(TAG, "Prepare");
}
};
// Small image loads without resize
// Picasso.get().load("http://www.theretirementmanifesto.com/wp-content/uploads/2016/08/Yoda-free-clip-art-680x410.jpg").into(mTarget);
// Mega high res out of memory image
Picasso.get().load("https://upload.wikimedia.org/wikipedia/commons" +
"/5/5e/M104_ngc4594_sombrero_galaxy_hi-res.jpg").
resize(100, 100).into(mTarget);
Also I'm assuming that the following line is in the manifest:
<uses-permission android:name="android.permission.INTERNET" />
Using this version of Picasso:
implementation 'com.squareup.picasso:picasso:2.71828'
Also it may be worth declaring the Target as a member variable due to issues Picaso has arising from 'weak references'. You will have to research this, but I believe it may be unsafe to declare the Target as an anonymous inner class.
Also it may be necessary to call resize(x, y) to prevent an out of memory situation depending on the image sizes and whether you control their source.
UPDATE:
The project won't work as written because it is using an synchronous solution, but you're making an asynchronous call:
holder.moviePosterIV.setImageBitmap(movie.getPosterBitmap());
The code:
public Bitmap getPosterBitmap() {
target = new Target() {
@Override
public void onBitmapLoaded(Bitmap bitmap, Picasso.LoadedFrom from) {
posterBitmap = bitmap;
}
@Override
public void onBitmapFailed(Exception e, Drawable errorDrawable) {}
@Override
public void onPrepareLoad(Drawable placeHolderDrawable) {}
};
return posterBitmap;
}
It cannot be done like this. In a nut shell, the Target is going to be called in the future when the image has been downloaded. But the code is being written as if the image is ready immediately.
It is a synchronous solution to an asynchronous problem. In synchronous programming we write 1 line after the other then return the result when the data is ready.
If we wrote it synchronously:
f() {
image = getImage(url) // the program could be blocked here for minutes
return image
}
So instead we do it asynchronously:
f() {
getImageInTheFuture(url, imageReadyFunc); // call imageReadyFunc when it is finally downloaded
}
imageReadyFunc(image) {
setTheImage();
}
The asynchronous solution prevents the app from blocking, but it is also a real pain because we can no longer use a 'return' statement. Instead we have to break the code up into 2 sections. Code that we can run before the image is available. Code that we can run after the image is available.
But under the hood Picasso is doing all of this work for you. I'd really advise against trying to manage the bitmaps directly. In the bad old days of Android before Picasso, Glide, etc. apps used to routinely crash and run out of memory trying to manage their own bitmaps. It is technically difficult to do without causing memory leaks and running out of memory.
Hope that makes sense...
I want get a bitmap use Picasso but fail
Your problem is that nothing keeps a strong reference to the Target instance so it gets garbage collected.
You can't just call new Target() { ... } because there aren't any strong references to it. You need to store it on a field in a view holder or implement it on a subclass of a view.
See this answer:
https://stackoverflow.com/a/30681395/5476209
this guy explicitly managed garbage collection issue happening in library.
Related Topics
Couldn't Load Memtrack Module Logcat Error
How to Get the Current Location Latitude and Longitude in Android
How to Access the Drawable Resources by Name in Android
Asynctask Won't Stop Even When the Activity Has Destroyed
Calling Activity Class Method from Service Class
How to Set Different Label for Launcher Rather Than Activity Title
How to Keep the Screen on in My App
"Rate This App"-Link in Google Play Store App on the Phone
Android Arraylist of Custom Objects - Save to Sharedpreferences - Serializable
Placing/Overlapping(Z-Index) a View Above Another View in Android
Android: Out of Memory Exception in Gallery
How to Dynamically Set the Position of View in Android
Android Sdk Manager Won't Open
Simple Parse JSON from Url on Android and Display in Listview
What to Use Instead of "Addpreferencesfromresource" in a Preferenceactivity