在毕加索中使用目标获取位图

Get Bitmap using a Target in Picasso

我正在开发电影 Android 应用程序,它从 API 获取电影列表,为所有电影提供海报路径。

我想从图像的 URL 中获取图像 Bitmap 以将其保存为模型 class 中的 Bitmap 变量。我想将图像保存为数据库中的 blob 以直接检索它,而无需在用户每次打开应用程序时重新下载。这可能吗?

我想做这样的事情,但它总是returns null。

 private Bitmap posterBitmap;

 public void setPosterBitmap () {
    Picasso.get().load(POSTERS_URL).into(new Target() {
        @Override
        public void onBitmapLoaded(Bitmap bitmap, Picasso.LoadedFrom from) {
            posterBitmap = bitmap; // I don't want to set it to an Image view here
        }

        @Override
        public void onBitmapFailed(Exception e, Drawable errorDrawable) {}

        @Override
        public void onPrepareLoad(Drawable placeHolderDrawable) {}
    });   
}

提前致谢。

这段代码对我有用:

...
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);

我还假设以下行在清单中:

<uses-permission android:name="android.permission.INTERNET" />

使用此版本的 Picasso:

implementation 'com.squareup.picasso:picasso:2.71828'

此外,由于 'weak references' 引起的 Picaso 问题,将 Target 声明为成员变量可能是值得的。您将不得不对此进行研究,但我认为将 Target 声明为匿名内部 class.

可能 是不安全的

此外,可能需要调用 resize(x, y) 以防止出现内存不足的情况,具体取决于图像大小以及您是否控制其来源。

更新:

该项目不会像写的那样工作,因为它使用的是同步解决方案,但您正在进行异步调用:

holder.moviePosterIV.setImageBitmap(movie.getPosterBitmap());

代码:

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;
}

这样是不行的。简而言之 shell,Target 将在将来下载图像时调用。但是正在编写代码,就好像图像立即准备就绪一样。

这是一个异步问题的同步解决方案。在同步编程中,我们一行接一行地写,然后 return 数据准备好后的结果。

如果我们同步写入:

  f() {
    image = getImage(url) // the program could be blocked here for minutes
    return image
  }

所以我们改为异步进行:

  f() {
    getImageInTheFuture(url, imageReadyFunc); // call imageReadyFunc when it is finally downloaded
  }

  imageReadyFunc(image) {
    setTheImage();
  }

异步解决方案可以防止应用程序阻塞,但这也是一个真正的痛苦,因为我们不能再使用 'return' 语句。相反,我们必须将代码分成两部分。在图像可用之前我们可以 运行 的代码。图片可用后我们可以运行的代码。

但在幕后,毕加索正在为您完成所有这些工作。我真的建议不要尝试直接管理位图。在 Picasso、Glide 等之前的 Android 糟糕的过去,应用程序经常崩溃并且 运行 内存不足试图管理自己的位图。在技​​术上很难做到不导致内存泄漏和 运行内存不足。

希望这是有道理的...

new Thread(() -> {
        try {
            Bitmap mBitmap = Picasso.get().load(link).get();
        } catch (Exception e) {
            Log.e(""+e);
        }
    }).start();

通过使用 实施 'com.squareup.picasso:picasso:2.71828'