Fresco: использовать текущее изображение, отображаемое в Drawee, в качестве заполнителя для следующего запроса.

Я воспроизводю несколько изображений последовательно на одном и том же SimpleDraweeView, проблема в том, что при отправке нового запроса imageURI SimpleDrweeView удалит текущее отображаемое изображение и ничем не заменит его, пока URI не будет загружен. Таким образом, это оставит пробелы в игровой последовательности (вы можете подумать, что я пытаюсь сделать мультяшную анимацию с использованием местных фотографий). Я хотел бы, чтобы SimpleDrweeView оставил текущее изображение как есть, пока новое не будет загружено, а затем просто замените его, когда оно будет готово.

Я попытался использовать схему низкого/высокого разрешения из этого билета, чтобы поместить старый uri в качестве заполнителя, но это не сработало (имело тот же эффект, что и раньше).

Это то, что у меня есть сейчас:

 SimpleDraweeView draweeView = (SimpleDraweeView) findViewById(R.id.my_image_view);

 draweeView.setImageURI(uri /* local image */); 

И это то, что я пробовал до сих пор (не работает):

                SimpleDraweeView draweeView = (SimpleDraweeView) findViewById(R.id.my_image_view);

            Uri lowResUri, highResUri;
            DraweeController controller = Fresco.newDraweeControllerBuilder().setTapToRetryEnabled(true)
                    .setLowResImageRequest(ImageRequest.fromUri((Uri) draweeView.getTag())) /*naive way to test the low/high res feature*/
                    .setImageRequest(ImageRequest.fromUri(uri))
                    .setOldController(draweeView.getController())
                    .build();
            draweeView.setTag(uri);
            draweeView.setController(controller); 

person Jimmy    schedule 26.11.2015    source источник


Ответы (1)


Я являюсь частью команды Fresco и могу помочь. Странно, что вы испытываете ту же проблему с комбинацией низкого/высокого разрешения. Если изображение отображается в данный момент, это означает, что оно должно быть в кеше растровой памяти, что, в свою очередь, означает, что оно должно быть в состоянии загрузиться немедленно, если установлено как изображение с низким разрешением в следующий раз, когда вы переключаетесь на следующий кадр. Вы уверены, что устанавливаете правильный uri как изображение с низким разрешением? (Uri) draweeView.getTag() выглядит подозрительно. Я бы перепроверил эту часть.

Если uri действительно правильный, но изображения больше нет в кеше растровых изображений, стоит выяснить, почему видимое изображение больше не кэшируется, поскольку у нас есть явная логика, которая должна предотвращать вытеснение видимых изображений. Узнайте, как отслеживать это с помощью подробного ведения журнала здесь.

Если все вышеперечисленное не помогло, третий вариант — реализовать собственный DataSource. Я могу помочь с этим, но это может быть несколько связано. Основная идея состоит в том, чтобы реализовать DataSource, который обертывает другой DataSource, фактически предоставляющий изображение. Тогда вы можете сделать что-то вроде этого:

// keep this instance somewhere
mMyDataSourceSupplier = new MyDataSourceSupplier();

// build controller by specifying your custom datasource supplier instead of specifying any URIs.
Fresco.newDraweeControllerBuilder()
  .setDataSourceSupplier(mMyDataSourceSupplier)
  .build()

// later, when you need to change the image do
mMyDataSourceSupplier.setUri(nextUri);

// this is just an outline
class MyDataSourceSupplier implements Supplier<DataSource<CloseableReference<CloseableImage>>> {

  private Uri mCurrentUri;
  private DataSource<CloseableReference<CloseableImage>> mCurrentDataSource;

  public void setUri(Uri uri) {
    mCurrentUri = uri;
    if (mCurrentDatasource != null) {
      mCurrentDataSource.setUri(uri);
    }
  }

  @Override
  public DataSource<CloseableReference<CloseableImage>> get() {
    mCurrentDataSource = new MyDataSource();
    mCurrentDataSource.setUri(uri);
    return mCurrentDataSource;
  }

  private class MyDataSource extends AbstractDataSource<CloseableReference<CloseableImage>> {
    private DataSource mUnderlyingDataSource;

    @Override
    protected void closeResult(@Nullable CloseableReference<CloseableImage> result) {
      CloseableReference.closeSafely(result);
    }

    @Override
    @Nullable
    public CloseableReference<CloseableImage> getResult() {
      return CloseableReference.cloneOrNull(super.getResult());
    }


    @Override
    public boolean close() {
      if (mUnderlyingDataSource != null) {
        mUnderlyingDataSource.close();
        mUnderlyingDataSource = null;
      }
      return super.close();
    }

    public void setUri(Uri uri) {
      if (mUnderlyingDataSource != null) {
        mUnderlyingDataSource.close();
        mUnderlyingDataSource = null;
      }
      if (uri != null && !isClosed()) {
        mUnderlyingDataSource = Fresco.getImagePipeline().fetchDecodedImage(ImageRequest.fromUri(uri), null);
        mUnderlyingDataSource.subscribe(new BaseDataSubscriber {
          @Override
          protected void onNewResultImpl(DataSource<List<CloseableReference<CloseableImage>>> dataSource) {
            MyDataSource.super.setResult(dataSource.getResult(), false);
          }
        });
      }
    }
  }
}
person plamenko    schedule 03.12.2015
comment
Большое спасибо за это. Я собираюсь попробовать это на следующей неделе и сообщу вам о результатах. - person Jimmy; 05.12.2015
comment
@plamenko, почему вы решили скрыть существующее изображение, когда началась загрузка нового? предоставление выбора скрыть это или нет кажется гораздо более полезным. - person Anton Malyshev; 03.08.2016
comment
@AntonMalyshev, дело не в том, что мы решили скрыть существующее изображение как таковое. Это скорее следствие конструкции Drawee. Drawee получает изображения для отображения из DataSource (который, в свою очередь, поступает из Supplier‹DataSource›). Drawee имеет только одного поставщика, что значительно упрощает проектирование, поскольку логика мультиплексирования инкапсулирована там, а не в контроллере Drawee. Чистый способ реализовать эту функциональность с помощью Drawee — иметь поставщика, который это делает. - person plamenko; 05.08.2016
comment
@AntonMalyshev, ...так что ваш вопрос лучше сформулировать как Почему Fresco не предоставляет такого поставщика из коробки?. Ответ прост: в то время в этом не было необходимости. Мы приветствуем запросы на вытягивание, и если предоставленный поставщик является достаточно общим и часто запрашиваемым, мы будем рады отправить его вместе с Fresco. - person plamenko; 05.08.2016