使用Picasso加载的ImageView如何获取Bitmap

10

我有一个方法来加载图片,如果这张图片之前没有被加载过,它会从服务器上寻找。然后将其存储在应用程序的文件系统中。如果它已经在文件系统中存在,那么就从文件系统中加载该图像,因为这比从服务器获取要快得多。如果您之前加载过该图像而没有关闭应用程序,则将其存储在静态字典中,以便可以重新加载而不使用更多内存,以避免内存不足错误。

这一切都很好,直到我开始使用Picasso图像加载库。现在我正在将图像加载到ImageView中,但是我不知道如何获得返回的位图,以便我可以将其存储在文件或静态字典中。这让事情变得更加困难,因为它意味着每次它都会试图从服务器加载图像,这并不是我想要发生的事情。是否有一种方法可以在将其加载到ImageView中后获得位图?下面是我的代码:

public Drawable loadImageFromWebOperations(String url,
        final String imagePath, ImageView theView, Picasso picasso) {
    try {
        if (Global.couponBitmaps.get(imagePath) != null) {
            scaledHeight = Global.couponBitmaps.get(imagePath).getHeight();
            return new BitmapDrawable(getResources(),
                    Global.couponBitmaps.get(imagePath));
        }
        File f = new File(getBaseContext().getFilesDir().getPath()
                .toString()
                + "/" + imagePath + ".png");

        if (f.exists()) {
            picasso.load(f).into(theView);

下面这行是我尝试检索位图,但它抛出了一个空指针异常,我猜这是因为Picasso需要一段时间将图片添加到ImageView中。

            Bitmap bitmap = ((BitmapDrawable)theView.getDrawable()).getBitmap();
            Global.couponBitmaps.put(imagePath, bitmap);
            return null;
        } else {
            picasso.load(url).into(theView);
            return null;
        }
    } catch (OutOfMemoryError e) {
        Log.d("Error", "Out of Memory Exception");
        e.printStackTrace();
        return getResources().getDrawable(R.drawable.default1);
    } catch (NullPointerException e) {
        Log.d("Error", "Null Pointer Exception");
        e.printStackTrace();
        return getResources().getDrawable(R.drawable.default1);
    }
}

非常感谢您的帮助!


Picasso不会每次都从服务器加载图像。只有在第一次加载后,它才会从缓存目录中加载。 - intrepidkarthi
5个回答

44

使用Picasso时,您无需自己实现静态字典,因为Picasso会自动完成。 @intrepidkarthi的说法是正确的,因为图片在第一次加载时会被Picasso自动缓存,因此不会不断调用服务器以获取相同的图片。

话虽如此,我发现自己处于类似的情况中:我需要访问下载的位图以便将其存储到我的应用程序的其他地方。 为此,我稍微修改了@Gilad Haimov的答案:

Java,使用旧版的Picasso:

Picasso.with(this)
    .load(url)
    .into(new Target() {

        @Override
        public void onBitmapLoaded (final Bitmap bitmap, Picasso.LoadedFrom from) {
            /* Save the bitmap or do something with it here */

            // Set it in the ImageView
            theView.setImageBitmap(bitmap); 
        }

        @Override
        public void onPrepareLoad(Drawable placeHolderDrawable) {}

        @Override
        public void onBitmapFailed(Drawable errorDrawable) {}
});

Kotlin,使用 Picasso 的 2.71828 版本:

Picasso.get()
        .load(url)
        .into(object : Target {

            override fun onBitmapLoaded(bitmap: Bitmap, from: Picasso.LoadedFrom) {
                /* Save the bitmap or do something with it here */

                // Set it in the ImageView
                theView.setImageBitmap(bitmap)
            }

            override fun onPrepareLoad(placeHolderDrawable: Drawable?) {}

            override fun onBitmapFailed(e: Exception?, errorDrawable: Drawable?) {}

        })

这样可以在异步加载位图的同时访问它,但您必须记得将其设置在ImageView中,因为不再自动完成。

另外,如果您想知道图像来自哪里,可以在同一方法中访问该信息。上述方法的第二个参数Picasso.LoadedFrom from是一个枚举,让您知道从哪个源加载了位图(三个源分别是DISKMEMORYNETWORK。(来源)。Square Inc. 还提供了一种视觉方式,通过使用这里解释的调试指示符来查看位图的加载位置。

希望这能帮到您!


onPrepareLoad和onBitmapFailed中的问号救了我的一天。 - mrahimygk
我无法覆盖目标方法,我收到错误消息“此类型是最终的,因此无法从中继承”。 - Alon
你使用的 Picasso 版本是什么?看起来它在最新版本中可能已经更名为“BitmapTarget”。 - jguerinet
1
只是提醒一下,以防有人犯我所犯的错误。请确保您选择了 com.square.picasso 中的 'Target' 接口,就像这样 https://i.stack.imgur.com/Xvmbb.png。否则,您将找不到 onBitmapLoaded 方法。上面的 Kotlin 代码对我有效。 - sarah
我尝试了相同的方法,但是图片没有在我的RecycleView中加载。 - Neal

8

Picasso可以直接控制下载的图片。要将下载的图片保存到文件中,请按以下方式操作:

Picasso.with(this)
    .load(currentUrl)
    .into(saveFileTarget);

地点:

saveFileTarget = new Target() {
    @Override
    public void onBitmapLoaded (final Bitmap bitmap, Picasso.LoadedFrom from){
        new Thread(new Runnable() {
            @Override
            public void run() {
                File file = new File(Environment.getExternalStorageDirectory().getPath() + "/" + FILEPATH);
                try {
                    file.createNewFile();
                    FileOutputStream ostream = new FileOutputStream(file);
                    bitmap.compress(CompressFormat.JPEG, 75, ostream);
                    ostream.close();
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        }).start();
    }
}

这个问题是否也可以使用Drawable来解决?(我正在尝试将其附加到EditText上)我没有收到任何错误信息,但它并没有起作用。 - Sauron

0

由于您正在使用Picasso,因此您可能希望充分利用它。它包括一个强大的缓存机制。

在您的Picasso实例上使用picasso.setDebugging(true)来查看发生了什么样的缓存(图像是从磁盘、内存还是网络加载的)。请参见:http://square.github.io/picasso/(调试指示器)

Picasso的默认实例配置为(http://square.github.io/picasso/javadoc/com/squareup/picasso/Picasso.html#with-android.content.Context-

可用应用程序RAM的15%的LRU内存缓存

磁盘缓存占用2%的存储空间,最多50MB,但不少于5MB。(注意:这仅适用于API 14+或者如果您使用提供所有API级别上的磁盘缓存的独立库,如OkHttp)

您还可以使用 Picasso.Builder 指定您的 Cache 实例以自定义您的实例,并且可以指定您的 Downloader 以进行更精细的控制。(在 Picasso 中有一个 OkDownloader 的实现,如果您在应用程序中包含 OkHttp,则会自动使用它。)

0
在这个例子中,我用来设置可折叠工具栏的背景。
public class MainActivity extends AppCompatActivity {

 CollapsingToolbarLayout colapsingToolbar;

  @Override
  protected void onCreate(Bundle savedInstanceState) {
      super.onCreate(savedInstanceState);

  colapsingToolbar = (CollapsingToolbarLayout) findViewById(R.id.colapsingToolbar);
  ImageView imageView = new ImageView(this);
  String url ="www.yourimageurl.com"


  Picasso.with(this)
         .load(url)
         .resize(80, 80)
         .centerCrop()
         .into(image);

  colapsingToolbar.setBackground(imageView.getDrawable());

}

我希望它对你有所帮助。

imageView.getDrawable() 为空。 - ghita

-1

使用这个

Picasso.with(context)
.load(url)
.into(imageView new Callback() {
    @Override
    public void onSuccess() {
        //use your bitmap or something
    }

    @Override
    public void onError() {

    }
});

希望它能帮到你


2
onSuccess() 不提供 Bitmap 对象。 - Hemanth

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接