【问题标题】:Flutter Web - Scrolling is very laggy for large number of imagesFlutter Web - 大量图像的滚动非常缓慢
【发布时间】:2020-11-30 17:25:33
【问题描述】:

我有一个基于通道 beta 构建的 Flutter 网站,用于上传大图像。 在 Chrome 上测试时,当有大量图像行时向下滚动非常滞后。

下面是代码的示例复制

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

void main() => runApp(MyApp());

class MyApp extends StatefulWidget {
  @override
  _MyAppState createState() => _MyAppState();
}

class _MyAppState extends State<MyApp> {
  DropzoneViewController controller1;
  String message1 = 'Drop something here';
  bool highlighted1 = false;
  List assets = [];
  @override
  Widget build(BuildContext context) => MaterialApp(
        home: Scaffold(
          appBar: AppBar(
            title: const Text('Dropzone example'),
          ),
          body: ListView(
            children: [
              if (assets.length > 0)
                _showAssets(assets)
              else
                buildZone1(context),
              Padding(
                padding: const EdgeInsets.all(30),
                child: Container(
                  width: 100,
                  child: MaterialButton(
                    color: Colors.greenAccent,
                    child: Text('Browse files'),
                    onPressed: () =>
                        controller1.pickFiles(multiple: true).then((files) {
                      files.forEach((file) {
                        controller1.createFileUrl(file).then((url) {
                          setState(() {
                            print('in set state');
                            assets.add(url);
                          });
                        });
                      });
                    }),
                  ),
                ),
              ),
              Container(height: 400, color: Colors.lightGreen),
              Container(height: 400, color: Colors.redAccent),
            ],
          ),
        ),
      );
  Widget _showAssets(List assets) {
    //print(assets);
    return Wrap(
      children: assets.map((asset) {
        return Container(
          height: 150,
          child: Image.network(asset),
        );
      }).toList(),
    );
  }

  Widget buildZone1(BuildContext context) => Builder(
        builder: (context) => Container(
          height: 200,
          child: DropzoneView(
            operation: DragOperation.copy,
            cursor: CursorType.grab,
            onCreated: (ctrl) => controller1 = ctrl,
            onLoaded: () => print('Zone 1 loaded'),
            onError: (ev) => print('Zone 1 error: $ev'),
            onHover: () {
              setState(() => highlighted1 = true);
              //print('Zone 1 hovered');
            },
            onLeave: () {
              setState(() => highlighted1 = false);
              //print('Zone 1 left');
            },
            onDrop: (ev) {
              print('Zone 1 drop: ${ev.name}');
              setState(() {
                print('in set state');
                message1 = '${ev.name} dropped';
                highlighted1 = false;
              });
            },
          ),
        ),
      );
}

pubspec.yaml

name: file_upload
description: A new Flutter project.


publish_to: 'none' 

https://developer.apple.com/library/archive/documentation/General/Reference/InfoPlistKeyReference/Articles/CoreFoundationKeys.html
version: 1.0.0+1

environment:
  sdk: ">=2.7.0 <3.0.0"

dependencies:
  flutter:
    sdk: flutter
  flutter_dropzone: ^1.0.9


  # The following adds the Cupertino Icons font to your application.
  # Use with the CupertinoIcons class for iOS style icons.
  cupertino_icons: ^1.0.1

dev_dependencies:
  flutter_test:
    sdk: flutter

# For information on the generic Dart part of this file, see the
# following page: https://dart.dev/tools/pub/pubspec

# The following section is specific to Flutter.
flutter:

  # The following line ensures that the Material Icons font is
  # included with your application, so that you can use the icons in
  # the material Icons class.
  uses-material-design: true

复制

  • 点击浏览文件并选择超过 2MB 的 50 到 100 张图像以显示超过 10 行
  • 当图像可见时尝试向下滚动

【问题讨论】:

    标签: image flutter web scroll


    【解决方案1】:

    您不会懒惰地构建图片。请改用ListView.builder

    关于默认 ListView 构造函数的文档说明:

    此构造函数适用于具有少量子项的列表视图,因为构造列表需要为可能显示在列表视图中的每个子项执行工作,而不仅仅是那些实际可见的子项。

    如果有 50 到 100 个 2MB 图片,您的计算机出现问题是可以理解的。

    文档指出ListView.builder 构造函数按需构建子级。

    ListView.builder 构造函数采用 IndexedWidgetBuilder,它根据需要构建子级。此构造函数适用于具有大量(或无限)子级的列表视图,因为仅对那些实际可见的子级调用构建器。

    例如

    ListView.builder(
      itemBuilder: (context, index) {
        if (assets.length > 0) {
          if (assets[index] == null) {
            return null;
          }
          return Container(
            height: 150,
            child: Image.network(assets[index]),
          );
        }
        else {
          if(index > 0) {
            return null;
          }
          return buildZone1(context);
        }
      },
    )
    

    【讨论】:

    • 看准了! List 的懒惰构建确实有助于滚动。我的生产代码使用 GridView.builder 并且我还使用 cacheExtent 来使滚动体验更流畅。非常感谢!。抱歉迟到了。
    【解决方案2】:

    我遇到了同样的问题,我通过在保持保真度的同时将图像压缩和缩小到尽可能低的形式来解决它。压缩图像在滚动时特别显示滞后的重大改进

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-10-14
      • 1970-01-01
      • 1970-01-01
      • 2018-05-28
      相关资源
      最近更新 更多