【问题标题】:Flutter SliverList freezes while its loading imagesFlutter SliverList 在加载图像时冻结
【发布时间】:2021-10-20 13:10:49
【问题描述】:

我有一个颤振应用程序。我的屏幕之一是从资产加载大量图像。有时我的应用程序在图像加载时冻结。
这是我的解决方案:我会放一个加载动画,这个动画需要在图像完成渲染后结束,但是我如何理解所有图像都完成了渲染?
如果您有任何其他解决方案,可以与我分享:)
这是加载图像的Widget 树,以防您需要知道。

final posts = [
    Post(
      ownerName: "McQueen95",
      avatarPath: "images/mcqueen.jpg",
      imagePaths: ['images/mcqueen.jpg'],
    ),
    Post(
      ownerName: "BugsBunny",
      imagePaths: ['images/Bugs_Bunny.png'],
    ),
    Post(
      ownerName: "Venom",
      imagePaths: ['images/venom.jpg'],
    ),
    Post(
      ownerName: "Po",
      imagePaths: ["images/kungfu_panda.jpg"],
      avatarPath: "images/po.jpg",
    ),
    Post(
      ownerName: "Po",
      imagePaths: ["images/kai.jpg", "images/oogway.jpg", "images/crane.png"],
      avatarPath: "images/po.jpg",
    ),
  ];
@override
  Widget build(BuildContext context) {
    return CustomScrollView(
      slivers: [
        SliverAppBar(
          title: Text("Cossy", style: TextStyle(color: Colors.purple)),
          // elevation: 0,
          pinned: true,
          // expandedHeight: 150.0,
          backgroundColor: backgroundColor,
          systemOverlayStyle: SystemUiOverlayStyle(
            systemNavigationBarColor: backgroundColor,
          ),
        ),
        SliverList(
          delegate: SliverChildBuilderDelegate(
            (context, index) => Padding(
              child: posts[index],
              padding: EdgeInsets.only(
                bottom: (index == posts.length - 1) ? 82 : 12,
              ),
            ),
            childCount: posts.length,
          ),
        )
      ],
    );
  }
import 'package:flutter/gestures.dart';
import 'package:flutter/material.dart';
import 'package:flutter_image_slider/carousel.dart';
class Post extends StatelessWidget {
  Post({
    Key? key,
    this.avatarPath,
    required this.ownerName,
    required this.imagePaths,
  }) : super(key: key);

  final String? avatarPath;
  final String ownerName;
  final List<String> imagePaths;

  @override
  Widget build(BuildContext context) {
    if (imagePaths.length == 0) return Text("no image?");
    return Container(
      decoration: BoxDecoration(
        boxShadow: [
          BoxShadow(
            color: Color(0xFFF2F2F2),
            offset: Offset(0.0, 1.0), //(x,y)
            blurRadius: 6.0,
          ),
        ],
        // color: Color(0xFFF2F2F2),
        color: Colors.deepOrange,
        borderRadius: BorderRadius.all(Radius.circular(10)),
      ),
      child: Column(
        children: [
          Padding(
            padding: const EdgeInsets.all(4.0),
            child: Row(
              children: [
                CircleAvatar(
                  child: avatarPath == null ? Icon(Icons.person) : null,
                  backgroundImage:
                      avatarPath == null ? null : AssetImage(avatarPath ?? ""),
                ),
                SizedBox(width: 10),
                Text(ownerName),
                Expanded(
                  child: SizedBox(height: 30),
                ),
                Icon(Icons.settings),
              ],
            ),
          ),
          Carousel(
            indicatorBarColor: Colors.transparent,
            autoScrollDuration: Duration(seconds: 2),
            animationPageDuration: Duration(milliseconds: 500),
            activateIndicatorColor: Colors.grey.shade200,
            animationPageCurve: Curves.bounceInOut,
            indicatorBarHeight: 30,
            indicatorHeight: 10,
            indicatorWidth: 20,
            unActivatedIndicatorColor: Colors.grey.shade700,
            stopAtEnd: true,
            autoScroll: false,
            // widgets
            items: imagePaths
                .map(
                  (imagePath) => Container(
                    decoration: BoxDecoration(color: Colors.black),
                    child: ConstrainedBox(
                      constraints: new BoxConstraints(
                        minHeight: 100,
                        minWidth: 100,
                        // maxHeight: 500,
                        maxHeight: MediaQuery.of(context).size.height * 3 / 2,
                        maxWidth: MediaQuery.of(context).size.width,
                      ),
                      child: FittedBox(
                        fit: BoxFit.scaleDown,
                        alignment: Alignment.center,
                        child: Image(
                          image: AssetImage("$imagePath"),
                        ),
                      ),
                    ),
                  ),
                )
                .toList(),
          ),
          Padding(
            padding: const EdgeInsets.only(
              left: 16,
              right: 16,
              top: 4,
            ),
            child: Row(
              children: [
                TextButton(
                  onPressed: () {
                    print(123);
                  },
                  child: Icon(
                    Icons.star_border_outlined,
                    size: 30,
                    // color: Colors.grey,
                  ),
                ),
                Expanded(
                  child: SizedBox(
                    height: 30,
                  ),
                ),
                Icon(
                  Icons.send_outlined,
                  size: 30,
                  // color: Colors.grey,
                ),
              ],
            ),
          ),
        ],
      ),
    );
  }
}

【问题讨论】:

  • 1.缩小图像。如果您要在 100x100 的框中显示它,则没有理由拥有 1000x1000 像素的图像。 2. 使用 Image.asset 中的 CachedHeight 和 CachedWidth 属性

标签: flutter flutter-widget


【解决方案1】:

我通过向包含图像的Widget 提供一定的高度和宽度值 解决了这个错误。使用ConstrainedBox 和FittedBox 意味着它将首先加载图像,然后测量所有项目的高度和宽度,然后将高度值赋予ListView。所以,这就是应用冻结的原因,测量 ListView 的大小需要很长时间。

我改变了这个:

Container(
  decoration: BoxDecoration(color: Colors.black),
  child: ConstrainedBox(
    constraints: new BoxConstraints(
      minHeight: 100,
      minWidth: 100,
      maxHeight: MediaQuery.of(context).size.height * 3 / 2,
      maxWidth: MediaQuery.of(context).size.width,
    ),
    child: FittedBox(
      fit: BoxFit.scaleDown,
      alignment: Alignment.center,
      child: Image(
        image: AssetImage("$imagePath"),
      ),
    ),
  ),
),

到这里:

AspectRatio(
  aspectRatio: 1 / 1,
  child: Container(
    decoration: BoxDecoration(color: Colors.black),
    width: MediaQuery.of(context).size.width,
    alignment: Alignment.center,
    child: ClipRRect(
      // borderRadius: BorderRadius.circular(10),
      child: Image(
        image: AssetImage("${imagePaths[0]}"),
      ),
    ),
  ),
),

【讨论】:

    猜你喜欢
    • 2014-07-29
    • 1970-01-01
    • 2020-02-26
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多