Белый флаг sh при перекрашивании изображения [трепетание] - PullRequest
0 голосов
/ 08 февраля 2020

Я пытаюсь построить сетку изображений с заданной шириной и высотой, оборачивая их внутри Containers и используя fit: BoxFit.fill, чтобы иметь возможность установить границу, если изображение выбрано (мне все равно, сохраняйте пропорции изображения, я хочу, чтобы у каждого контейнера была одинаковая общая ширина и высота).

Проблема в том, что я замечаю белый цвет sh, когда изображение перекрашивается после того, как на него постучали , Похоже, этого не происходит, когда изображений немного, но с 15+ изображениями это шумно.

Я попытался добавить gaplessPlayback: true в виджет изображения, как я нашел здесь , но это не решило мою проблему.

Вот рисунок, который показывает мою проблему (я использовал 16 изображений, размер 1920x1080):

РЕДАКТИРОВАТЬ:

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

enter image description here

И это мой код:

import 'dart:io';

import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';

void main() {
  // See https://github.com/flutter/flutter/wiki/Desktop-shells#target-platform-override
  debugDefaultTargetPlatformOverride = TargetPlatform.fuchsia;
  runApp(new MyApp());
}

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      debugShowCheckedModeBanner: false,
      home: Scaffold(body: ImageGridView()),
    );
  }
}

class ImageGridView extends StatelessWidget {
  List<File> _fileList = [];
  ImageGridView(){
    _fileList = [
        File('C:/flutter/img/1.jpg'),
        File('C:/flutter/img/3.jpg'),
        File('C:/flutter/img/4.jpg'),
        File('C:/flutter/img/5.jpg'),
        File('C:/flutter/img/6.jpg'),
        File('C:/flutter/img/7.jpg'),
        File('C:/flutter/img/8.jpg'),
        File('C:/flutter/img/9.jpg'),
        File('C:/flutter/img/10.jpg'),
        File('C:/flutter/img/11.jpg'),
        File('C:/flutter/img/12.jpg'),
        File('C:/flutter/img/13.jpg'),
        File('C:/flutter/img/14.jpg'),
        File('C:/flutter/img/15.jpg'),
        File('C:/flutter/img/16.jpg'),
      ];
    }

  @override
  Widget build(BuildContext context) {
    return SingleChildScrollView(
      child: Wrap(
        children: _fileList.map((file) {
          return WindowsAsset(file);
        }).toList(),
      ),
    );
  }
}

class WindowsAsset extends StatefulWidget {
  final File _file;

  WindowsAsset(this._file);

  @override
  State<StatefulWidget> createState() => WindowsAssetState();
}

class WindowsAssetState extends State<WindowsAsset> {
  bool selected = false;

  @override
  Widget build(BuildContext context) {
    final width = MediaQuery.of(context).size.width / 2;
    final height = width * 1080 / 1920;
    return Container(
      width: width,
      height: height,
      child: Container(
        child: Container(
          constraints: BoxConstraints.expand(),
          decoration: !selected
              ? null
              : BoxDecoration(
                  border: Border.all(
                    color: Color.fromRGBO(153, 209, 255, 1),
                    width: 4
                  ),
                ),
          child: Container(
            child: GestureDetector(
              child: Image.file(
                widget._file,
                filterQuality: FilterQuality.medium,
                fit: BoxFit.fill,
                gaplessPlayback: true,
              ),
              onTap: () => setState(() {
                selected = !selected;
              }),
            ),
          ),
        ),
      ),
    );
  }
}

Как я могу решить Это? Спасибо!

1 Ответ

1 голос
/ 08 февраля 2020

Это, вероятно, из-за сочетания 1. ограничений ImageCache и 2. вложения всех ваших изображений в Wrap

ImageCache имеет максимальное количество изображений, которые он может кэшировать в памяти, а также максимальное количество общих байтов. Когда этот предел достигнут, старые изображения выселяются, чтобы освободить место для новых. При попытке отобразить изображение, которое ранее было извлечено из кэша, потребуется некоторое время, чтобы снова загрузить его в память, поэтому белый флаг sh. Вы можете изменить пределы кэша в соответствии с Как изменить или заменить ImageCache в Flutter?

Пределы кэша изображений по умолчанию - 1000 различных изображений и всего 100 МБ, которые обычно достаточно, учитывая оптимальную компоновку, в которой виджеты вне экрана не создаются.

Wrap может быть главной причиной вашей проблемы - я считаю, что он внутренне создает все свои дочерние элементы, чтобы выяснить, как обернуть их. В вашем случае это были бы все изображения. Возможно, из-за Wrap все ваши изображения считаются на экране и поэтому не удаляются из кэша - это объясняет, почему некоторые изображения в GIF мигают, даже если вы не перестраиваете все дерево виджетов - потому что эти изображения не кэшируются, потому что кэш заполнен, и ни одно из изображений не может быть удалено.

Возможно, вы захотите заменить Wrap на GridView.builder, который будет создавать только экранные виджеты.

Вы можете столкнуться с той же проблемой, если изображения слишком велики, чтобы вместить в кеш столько данных, сколько вы отображаете одновременно. Если вы отображаете изображение размером 50 МБ в контейнере 10x10, это все равно занимает 50 МБ кэш-памяти в памяти.

...