在毕加索中使用目标获取位图 [英] Get Bitmap using a Target in Picasso

查看:114
本文介绍了在毕加索中使用目标获取位图的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在使用电影Android应用程序,该应用程序通过API提供电影列表,该API提供了所有电影的海报路径.

I'm working on movies Android app which get list of movies from an API which provides a poster path for all movies.

我想从图像的URL中以 Bitmap 的形式获取图像,以将其另存为模型类中的 Bitmap 变量.我想将图像另存为数据库中的blob,以便直接检索它,而无需每次用户打开应用程序时都重新下载它.有可能吗?

I want to get the image as Bitmap from the image's URL to save it as a Bitmap variable in the model class. I want to save the image as blob in the DB to retrieve it directly without redownloading it each time the user opens the app. Is that possible?

我想做这样的事情,但是它总是返回null.

I want to do something like this, but it always 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);

我还假设清单中包含以下行:

Also I'm assuming that the following line is in the manifest:

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

使用此版本的毕加索:

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

由于Picaso因弱引用"引起的问题,可能还需要将Target声明为成员变量.您将必须对此进行研究,但我认为将目标声明为匿名内部类 可能是不安全的.

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.

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

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.

更新:

该项目将无法正常运行,因为它使用的是同步解决方案,但是您正在进行异步调用:

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

代码:

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

无法做到这一点.简而言之,在下载图像后,将在将来调用Target.但是正在编写代码,就像立即准备好映像一样.

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.

如果我们同步编写它:

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

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

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.

但是,毕加索在幕后为您完成了所有这些工作.我真的建议不要尝试直接管理位图.在Android糟糕的日子里,在Picasso,Glide等应用程序经常崩溃并用尽内存来尝试管理自己的位图之前,这些应用程序就曾如此.从技术上讲,如果不引起内存泄漏和内存不足,很难做到这一点.

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.

希望如此...

这篇关于在毕加索中使用目标获取位图的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆