Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Picasso: load images to widget listview

I'm implementing widget with listview based on this tutorial: http://laaptu.wordpress.com/2013/07/24/populate-appwidget-listview-with-remote-datadata-from-web/ (source code: https://github.com/laaptu/appwidget-listview/tree/appwidget-listview2/).

ListView item contains text & image, for image loading I use Picasso.

getViewAt implementation:

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

When the image loaded, it breaks layout.

What can be a possible problem? Or what am I doing wrong?

Without image loading:

screenshot

How it looks after image is loaded:

screenshot

UPDATE:

The same happens if I just add a few nested remote views (all inflated from one layout)

UPDATE2:

Reported an issue: https://github.com/square/picasso/issues/587

like image 676
ab.helly Avatar asked Jul 16 '14 02:07

ab.helly


3 Answers

After struggling with this myself, I decided that blocking the background thread was ok (using .get() with Picasso) and was able to get the following to work inside my adapter:

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

If you know the size of the image coming back (if it's always the same or you can predict it), you might want to do something like this as well to cut down on resize jitters:

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

Performance is very smooth, no loading jitters, I'm pretty happy with the result.

like image 162
wblaschko Avatar answered Oct 23 '22 11:10

wblaschko


This support has been added now, thanks to the great guys at square

This is how I've used it

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

Enjoy the buttery smooth scrolling :)

like image 27
ngatirauks Avatar answered Oct 23 '22 12:10

ngatirauks


you can use Target Callback to handle your issue like this

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

for more details check this article

like image 36
3zcs Avatar answered Oct 23 '22 11:10

3zcs