使用缩略图作为Picasso的占位符

7

从用户体验的角度来看,最好先向用户显示缩略图,直到真实图像完成加载,然后再向用户展示它。但是,Picasso 仅使用一个资源文件作为占位符,类似于:

Picasso.with(context)
    .load(url)
    .placeholder(R.drawable.user_placeholder)
    .into(imageView);

那么,我如何使用缩略图URL作为占位符?如果我需要两次使用Picasso,那该怎么做呢?

已经在Picasso的GitHub页面上开了一个问题,请求添加此功能。但像JakeWharton所说,似乎不会将其添加到Picasso中。那么我们可以如何利用手头现有的资源进行操作呢?


手动设置ImageView的缩略图怎么样?您可以不使用Picasso的占位符选项,这样在加载完成之前就有了缩略图。 - akohout
手动是什么意思? - AbdelHady
3个回答

33

感谢 raveN 和在 GitHub 上关于 原始请求 的评论,最终我找到了一个可行的解决方案:

Picasso.with(context)
       .load(thumb) // thumbnail url goes here
       .into(imageView, new Callback() {
            @Override
            public void onSuccess() {
                Picasso.with(context)
                        .load(url) // image url goes here
                        .placeholder(imageView.getDrawable())
                        .into(imageView);
            }
            @Override
            public void onError() {

            }
        });

这里的技巧是在第一次调用后从imageView(即缩略图)中获取drawable,并将其作为占位符传递给第二次调用。

-- 更新 --

我写了一篇博客文章描述了整个情景。


我正在使用相同的代码,但是缩略图没有被设置。即使thumbImageUrl获取了正确的值。Picasso.get().load(thumbImageUrl) .placeholder(R.drawable.ic_avatar) .into(mUserProfileImageView, new Callback() { @Override public void onSuccess() { Picasso.get().load(imageUrl) .placeholder(R.drawable.ic_avatar) .into(mUserProfileImageView); } @Override public void onError(Exception e) { } }); - xaif
@xaif 我之前使用的是较旧版本的Picasso,这里回答中的代码对我来说运行良好,但我还没有尝试最新版本,所以我不确定你的代码出了什么问题。 - AbdelHady
谢谢您的回复,请告诉我您尝试最新版本的时间。顺便说一下,我的问题还没有解决。 - xaif

3
您可以编写一个简单的辅助工具,调用 Picasso 两次(正如您所提到的)。
我尚未测试它,但应该像这样进行:
Picasso.with(context)
        .load(thumbnailUrl)
        .error(errorPlaceholderId)
        .into(imageView, new Callback() {
                        @Override
                        public void onSuccess() {
                                // TODO Call Picasso once again here
                        }

                        @Override
                        public void onError() {                             
                    }
            );

有几种不同的方法可以让您的 Picasso 被调用两次。我能想到的一种方法(再次强调,未经测试)是:
public static void loadImageWithCallback(String url, Callback callback) {
    Picasso.with(context)
        .load(url)
        .error(errorPlaceholderId)
        .into(imageView, callback);
}

public static void loadImage(String url) {
    Picasso.with(context)
        .load(url)
        .error(errorPlaceholderId)
        .into(imageView);
}

loadImageWithCallback("http://example.com/mythumbnail.jpg", new Callback() {

                    @Override
                    public void onSuccess() {
                        loadImage("http://example.com/myRealImage.jpg");    
                    }

                    @Override
                    public void onError() {                             
                }
}

编辑:我知道的是 Picasso 提供了这个回调机制。我在我的应用中使用它来隐藏一个 ProgressBar,该 ProgressBar 在图像加载完成之前显示。我将在成功或错误回调中隐藏它,因此您可以选择在图像加载完成时收到通知。然后您可以简单地再次调用它。我希望上述方法有效。


1
很快,它就不能工作了。不幸的是,当Picasso将ImageView绑定到它时似乎会清除它,因此当onSuccess()被调用并尝试在其上进行第二次调用时,它会清除加载的缩略图! 我认为我们需要获取从第一个调用中检索到的位图,并将其传递作为下一个占位符..但是如何做到呢?!! - AbdelHady

1

我最初使用了AbdelHady的解决方案,但发现只有在缩略图加载完成后才会加载更大的图像,因此我提出了这个解决方案。

假设您的项目中有一个实用程序类;

public final class U {

public static void picassoCombo(final RequestCreator thumbnail,
                                final RequestCreator large,
                                final ImageView imageView) {
    Target target = new Target() {
        @Override
        public void onBitmapLoaded(Bitmap bitmap, Picasso.LoadedFrom from) {
            imageView.setImageBitmap(bitmap);
        }

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

        @Override
        public void onPrepareLoad(Drawable placeHolderDrawable) {
            thumbnail.into(imageView);
        }
    };

    imageView.setTag(target); // To prevent target from being garbage collected
    large.into(target);
}
}

使用方法:

U.picassoCombo(
        Picasso.with(context)
                .load("http://lorempixel.com/200/100/sports/1/")
                .placeholder(R.drawable.ic_image_placeholder),
        Picasso.with(context)
                .load("http://lorempixel.com/800/400/sports/1/")
                .error(R.drawable.ic_image_broken),
        imageView
);

在上面的例子中,首先设置了占位符,接着设置缩略图url,无论缩略图请求是否完成、成功或失败,一旦大图像请求完成,就会进行设置。如果大图像请求失败,则设置错误可绘制对象。
唯一的问题是,如果使用setIndicatorsEnabled(true),则调试指示器不会显示大请求。据我所知,根据this issue convo,这似乎是设计如此。

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