Just saw a bunch of these crashes in my logs after updating to 2.3.2. Never had an issue with older versions.
java.lang.IllegalStateException: Method call should happen from the main thread.
at com.squareup.picasso.Utils.checkMain(Utils.java:122)
at com.squareup.picasso.RequestCreator.into(RequestCreator.java:351)
at com.cluster.services.GcmIntentService.getPhoto(GcmIntentService.java:225)
at com.cluster.services.GcmIntentService.sendNotification(GcmIntentService.java:95)
at com.cluster.services.GcmIntentService.onHandleIntent(GcmIntentService.java:65)
at android.app.IntentService$ServiceHandler.handleMessage(IntentService.java:65)
at android.os.Handler.dispatchMessage(Handler.java:99)
at android.os.Looper.loop(Looper.java:137)
at android.os.HandlerThread.run(HandlerThread.java:61)
private void getPhoto(String url, final int position) {
Picasso.with(getApplicationContext()).load(url).into(new Target() {
@Override
public void onPrepareLoad(Drawable arg0) {
}
@Override
public void onBitmapLoaded(Bitmap bm, LoadedFrom arg1) {
checkPhoto(bm, position);
}
@Override
public void onBitmapFailed(Drawable arg0) {
}
});
}
I also use Picasso to load images for notifications in the background.
On Jun 10, 2014 2:46 PM, "pfives" [email protected] wrote:
Just saw a bunch of these crashes in my logs after updating to 2.3.2.
Never had an issue with older versions.java.lang.IllegalStateException: Method call should happen from the main thread.
at com.squareup.picasso.Utils.checkMain(Utils.java:122)
at com.squareup.picasso.RequestCreator.into(RequestCreator.java:351)
at com.cluster.services.GcmIntentService.getPhoto(GcmIntentService.java:225)
at com.cluster.services.GcmIntentService.sendNotification(GcmIntentService.java:95)
at com.cluster.services.GcmIntentService.onHandleIntent(GcmIntentService.java:65)
at android.app.IntentService$ServiceHandler.handleMessage(IntentService.java:65)
at android.os.Handler.dispatchMessage(Handler.java:99)
at android.os.Looper.loop(Looper.java:137)
at android.os.HandlerThread.run(HandlerThread.java:61)
private void getPhoto(String url, final int position) {
Picasso.with(getApplicationContext()).load(url).into(new Target() {@Override public void onPrepareLoad(Drawable arg0) { } @Override public void onBitmapLoaded(Bitmap bm, LoadedFrom arg1) { checkPhoto(bm, position); } @Override public void onBitmapFailed(Drawable arg0) { } }); }—
Reply to this email directly or view it on GitHub
https://github.com/square/picasso/issues/547.
This was a mistake of the older versions. Do not invoke Picasso in a background thread as view recycling and other stuff can break.
You are better off spinning up your own thread and use get() instead.
The original code is also wrong for using target as an anonymous class.
@bobz what do you mean? I dont understand your problem.
Is there a specific Picasso reason to not use an anonymous class (other than it will be instantiated more than once so is a bit wasteful)?
I think @bobz and I are doing the same thing. Using Picasso to load images into RemoteViews for push notifications.
Picasso has RemoteViews support now.
IntentService runs the tasks in a bg thread. You are better off using that thread to load your bitmap also.
I'd like to be able to invoke Picasso from an intent service to download
images for Notifications. I'd like take advantage of Picasso's cache
management and Bitmap loading optimizations. Is this unsupported?
On Tue, Jun 10, 2014 at 3:38 PM, Dimitris [email protected] wrote:
IntentService runs the tasks in a bg thread. You are better off using
that thread to load your bitmap also.—
Reply to this email directly or view it on GitHub
https://github.com/square/picasso/issues/547#issuecomment-45661230.
As we said there is remoteviews support that includes all the caching etc you need. Just invoke it and it will do everything for you.
Does the main thread restriction apply when invoking into(RemoteViews...) ?
My Gcm messages are picked up on an IntentService, which AFAIK is the best
practice. Would be awkward to go back to the main thread just to call
Picasso.
On Tue, Jun 10, 2014 at 4:09 PM, Dimitris [email protected] wrote:
As we said there is remoteviews support that includes all the caching etc
you need. Just invoke it and it will do everything for you.—
Reply to this email directly or view it on GitHub
https://github.com/square/picasso/issues/547#issuecomment-45664809.
You were essentially already calling Picasso async from a bg thread to another bg thread.
There is no problem into going back to main thread for this. Picasso must be invoked from main in those calls to ensure recycling/canceling works.
I do understand the concern/pain here but with our cache control API you would be able to query if the image is there synchronously and the invoke it.
I'll need to think more about IntentService cases.
@bobz yea just throw your Picasso load call into a runnable posted by a handler instantiated in onCreate() of your IntentService and it should be all good.
Cool, yea, I can do that, it's just a lot of threads for a very simple
process.
Given that, in this (not totally uncommon) case, I have no need of row
recycling logic, would it make sense to add a builder method that disables
the row recycling logic (and its corresponding main thread requirement)?
On Tue, Jun 10, 2014 at 5:50 PM, pfives [email protected] wrote:
@bobz https://github.com/bobz yea just throw your Picasso load call
into a runnable posted by a handler instantiated in onCreate() of your
IntentService and it should be all good.—
Reply to this email directly or view it on GitHub
https://github.com/square/picasso/issues/547#issuecomment-45676675.
There is no distinction between recycling logic and no recycling logic. The target passed is used for recycling.
You could easily implement your own Target and provide recycling as well. Typically the view is used for recycling but nothing stops you for a custom strategy.
Closing this.
Quick workaround is performing the method call on a Handler on the main Looper.
Handler uiHandler = new Handler(Looper.getMainLooper());
uiHandler.post(new Runnable(){
@Override
public void run() {
Picasso.with(mContext).load(formatStaticImageUrlWith(location)).transform(new StaticMapTransformation()).into(remoteView, R.id.static_map_image, Constants.NOTIFICATION_ID_NEW_TRIP_OFFER, notification);
}
});
Had similar error in v2.3.4. I used the above solution on my widget app and the app no longer crashed, however, my widget UI got distorted.
@NikolaDespotoski Thanks for help
I wanted to mention that @dnkoutso recommendation of using the get() worked great on a bg thread. I used it for the large icon bitmap on a notification.
Most helpful comment
Quick workaround is performing the method call on a
Handleron the main Looper.