毕加索:将图像加载到小部件列表视图

Posted

技术标签:

【中文标题】毕加索:将图像加载到小部件列表视图【英文标题】:Picasso: load images to widget listview 【发布时间】:2014-09-06 10:07:03 【问题描述】:

我正在根据本教程使用列表视图实现小部件:http://laaptu.wordpress.com/2013/07/24/populate-appwidget-listview-with-remote-datadata-from-web/(源代码:https://github.com/laaptu/appwidget-listview/tree/appwidget-listview2/)。

ListView 项目包含文本和图像,我使用 Picasso 加载图像。

getViewAt 实现:

public RemoteViews getViewAt(int position) 
    final RemoteViews remoteView = new RemoteViews(context.getPackageName(), R.layout.listview_item);
    ListItem listItem = listItemList.get(position);
    remoteView.setTextViewText(R.id.headline, listItem.headline);
    final String imageUrl = listItem.image;
    handler.post(new Runnable() 
        @Override
        public void run() 
            if (!Utils.isEmpty(imageUrl)) 
                picasso.load(imageUrl)
                        .placeholder(R.drawable.empty_photo)
                        .into(remoteView, R.id.picture, new int[]  appWidgetId );
            
        
    );

    return remoteView;

当图像加载时,它会破坏布局。

可能会出现什么问题?或者我做错了什么?

不加载图片:

图片加载后的样子:

更新:

如果我只添加几个嵌套的远程视图(全部从一个布局膨胀),也会发生同样的情况

更新 2:

报告了一个问题:https://github.com/square/picasso/issues/587

【问题讨论】:

【参考方案1】:

在自己解决了这个问题之后,我决定阻止后台线程是可以的(将 .get() 与 Picasso 一起使用)并且能够在我的适配器中得到以下工作:

    @Override
    public RemoteViews getViewAt(int position) 
        DBItem item = list.get(position);
        RemoteViews view = new RemoteViews(context.getPackageName(), R.layout.widget_item);
        try 
            Bitmap b = Picasso.with(context).load(item.getImageUrl()).get();
            view.setImageViewBitmap(R.id.widget_image, b);
         catch (IOException e) 
            e.printStackTrace();
        
        view.setTextViewText(R.id.widget_title, item.getTitle());
        return view;
    

如果您知道返回的图像的大小(如果它始终相同或者您可以预测),您可能还想做这样的事情来减少调整大小的抖动:

    @Override
    public RemoteViews getLoadingView() 
        return new RemoteViews(context.getPackageName(), R.layout.v2_widget_item_loading);
    

性能非常流畅,没有加载抖动,我对结果很满意。

【讨论】:

我应该说我的表现很糟糕。但我 +1 这个答案,因为它只需要一点改进。在调用 .get() 之前调用 .fetch() 以便后续调用同一张图片(当用户上下滚动时)将足够快。 2021,这仍然是最好的解决方案。 with(context) 已弃用。用Picasso.get().load(/*URL*/).get() 更改它注意两个得到?两者都不一样。【参考方案2】:

现在已添加此支持,感谢 Square 的好人

我就是这样用的

Picasso.with(mContext)
.load(imagePath)
.into(remoteViews, R.id.some_id, new int[] mAppWidgetId);

享受黄油般流畅的滚动:)

【讨论】:

@ab.helly 是的,你是对的。不幸的是,这在列表视图中不起作用,因为毕加索需要回调主线程。在 listview 远程服务中,您已经在后台线程上。我也解决了这个问题,将缓存的位图存储在地图中并以这种方式提供服务。我最初使用 Picasso 获取它们并调整大小以确保最佳性能。 如何在远程视图工厂中获取 mAppWidgetId,例如。列表视图【参考方案3】:

您可以像这样使用 Target Callback 来处理您的问题

 Picasso.with(mContext)
                        .load(imageUrl)
                        .placeholder(R.drawable.defimage)
                        .into(new Target() 
                            @Override
                            public void onBitmapLoaded(Bitmap bitmap, Picasso.LoadedFrom from) 
                                mRemoteViews.setImageViewBitmap(R.id.myImage,bitmap);
                            

                            @Override
                            public void onBitmapFailed(Drawable errorDrawable) 
                                //do something when loading failed 
                            

                            @Override
                            public void onPrepareLoad(Drawable placeHolderDrawable) 
                               //do something while loading                                
                        );

更多详情请查看article

【讨论】:

那个 Target 会非常快地收集垃圾。 Picasso 对 Targets 的引用很少。只要您希望它存在,您就应该保留对 Target 的引用。

以上是关于毕加索:将图像加载到小部件列表视图的主要内容,如果未能解决你的问题,请参考以下文章

毕加索加载横向图像但不将纵向加载到标记的信息窗口中

将毕加索图像设置为 ListView 背景

毕加索未能从用bangla写的url加载图像

如何在不模糊或使用毕加索的情况下调整图像大小

如何将图像从 url 加载到小部件的 android 远程视图中

毕加索在 ListFragment 中有很多大位图