Picasso: загрузка изображений в виджет списка

Я реализую виджет со списком на основе этого урока: 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;
}

Когда изображение загружено, оно нарушает макет.

В чем может быть возможная проблема? Или что я делаю не так?

Без загрузки изображения:

screenshot

Как это выглядит после загрузки изображения:

screenshot

UPDATE:

То же самое происходит, если я просто добавляю несколько вложенных удаленных представлений (все раздуто из одного макета)

UPDATE2:

Сообщил о проблеме: 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);
    }

Производительность очень плавная, нет дрожания при загрузке, я очень доволен результatom.

Ответ 2

Эта поддержка была добавлена сейчас, благодаря отличным парням на площади

Вот как я это использовал

Picasso.with(mContext)
.load(imagePath)
.into(remoteViews, R.id.some_id, new int[] {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                                }
                        });

для более подробной информации проверьте эту статью