Synchronous image loading on a background thread with Picasso - without .get()

余生颓废 提交于 2019-12-01 08:28:30

问题


I have a custom viewgroup (that contains Picasso-loaded images) that can be reused in two places:

  1. Displayed to the user in the application (on the UI thread)
  2. Drawn to a canvas and saved as a .jpeg (on the background thread)

My code for drawing to the canvas looks like this:

int measureSpec = View.MeasureSpec.makeMeasureSpec(width, View.MeasureSpec.EXACTLY);
view.measure(measureSpec, measureSpec);
Bitmap bitmap =
      Bitmap.createBitmap(view.getMeasuredWidth(), view.getMeasuredHeight(), Bitmap.Config.ARGB_8888);
Canvas canvas = new Canvas(bitmap);
view.layout(0, 0, view.getMeasuredWidth(), view.getMeasuredHeight());
view.draw(canvas);

The problem is that there is no time for the image to load before I draw the view to the canvas. I'm trying to avoid coupling as much as possible here so I'd prefer not to add a Picasso callback because the class that's doing the drawing doesn't know anything about the view that it's drawing.

I'm currently working around the issue by changing the image loading code to .get() rather than .load() and then using imageView.setImageBitmap(). Unfortunately, this adds a ton of complexity to the view and I really don't like it.

What I'd like to do is pass an option to Picasso's RequestCreator that the request should be executed synchronously on the current thread (and throw an exception if it's the main thread). I wonder if this is too much of an edge case for support to be built directly into Picasso? Or is it already in the API and I'm oblivious to it?


回答1:


Here is my solution:

/**
 * Loads the request into an imageview.
 * If called from a background thread, the request will be performed synchronously.
 * @param requestCreator A request creator
 * @param imageView The target imageview
 * @param callback a Picasso callback
 */
public static void into(RequestCreator requestCreator, ImageView imageView, Callback callback) {
  boolean mainThread = Looper.myLooper() == Looper.getMainLooper();
  if (mainThread) {
    requestCreator.into(imageView, callback);
  } else {
    try {
      Bitmap bitmap = requestCreator.get();
      imageView.setImageBitmap(bitmap);
      if (callback != null) {
        callback.onSuccess();
      }
    } catch (IOException e) {
      if (callback != null) {
        callback.onError();
      }
    }
  }
}



回答2:


Perfect answer by Jacob Tabak

Here is small addition that handles the case if you load image into Target. I haven't found a way to get the origin of image to pass appropriate LoadedFrom argument.

 public static void into(RequestCreator requestCreator, Drawable placeHolder, Drawable errorDrawable, Target target) {
        boolean mainThread = Looper.myLooper() == Looper.getMainLooper();
        if (mainThread) {
            requestCreator.into(target);
        } else {
            try {
                target.onBitmapFailed(placeHolder);
                Bitmap bitmap = requestCreator.get();
                target.onBitmapLoaded(bitmap, Picasso.LoadedFrom.MEMORY);
            } catch (IOException e) {
                target.onBitmapFailed(errorDrawable);
            }
        }
    }


来源:https://stackoverflow.com/questions/27239203/synchronous-image-loading-on-a-background-thread-with-picasso-without-get

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!