问题
We are working on a share mode for photos in an app, and one of the share options is to load an overlay for the image online. If the user shares the photo before the overlay finishes loading we are sending an intent with the unmodified image to share to other apps with startActivityForResult, and then in onActivityResult we are returning the user to the normal photo view from the share view.
The issue we are running into is that when the user returns from sharing the photo, onActivityResult isn't called until the background thread that is loading the overlay finishes. Is there a reason that a background thread would suddenly start to block the UI thread?
Here is the code we are using inside of our overlay view class which extends ImageView to manage this:
private void asyncLoadImage() {
new Thread(new Runnable() {
@Override
public void run() {
loadImage();
}
}).start();
}
private void loadImage() {
try {
overlayBitmap = Picasso.with(getContext()).load(url).get();
if (overlayBitmap != null) {
displayBitmap();
} else {
displayError();
}
} catch (IOException ignored) {
displayError();
}
}
We have tried using Picasso targets as well instead of creating our own thread and we run into the exact same issue, the only solution so far has been to use Ion asynchronously (however, using Ion synchronously or trying to cancel the Ion request futures before we call startActivityForResult result in the same UI thread blocking issues). This feels like a huge hack since we are using Picasso everywhere else in the app.
Is there a reason why these background tasks would be blocking the UI thread when returning to the activity?
回答1:
Looking at your code you are creating a new thread when you don't need to. Picasso has a configurable executor method for threading.
I had an issue when loading over 100+ images using picasso and it would lock up and block the UI Thread on me but this was due to it creating a new Thread every time I called picasso to get an image. I solved this by doing a little research and found that within picasso there is a configurable executor method.
This is my ImageHandler class implementation
public class ImageHandler {
private static Picasso instance;
public static Picasso getSharedInstance(Context context)
{
if(instance == null)
{
instance = new Picasso.Builder(context).executor(Executors.newSingleThreadExecutor()).memoryCache(Cache.NONE).indicatorsEnabled(true).build();
return instance;
}
else
{
return instance;
}
}
}
I don't know that this is your issue, but it would be worth a try if you haven't implemented it yet.
Here is the way I use it to load images
ImageHandler.getSharedInstance(getApplicationContext()).load(imString).skipMemoryCache().resize(width, height).into(image, new Callback() {
@Override
public void onSuccess() {
layout.setVisibility(View.VISIBLE);
}
@Override
public void onError() {
}
});
来源:https://stackoverflow.com/questions/28995855/why-does-picasso-running-in-a-background-thread-block-onactivityresult