抖动图像预加载

时间:2018-07-14 22:04:07

标签: dart flutter

是否可以以某种方式预加载应用程序上的图像开始?就像我的抽屉里有背景图像,但是第一次打开抽屉时,我可以看到图像闪烁,就像从资产中取出然后显示一样,一旦我第一次看到它,就会给我带来不好的体验抽屉的开口行为正常,因为它已被缓存。我想在应用程序加载时预取它,所以没有这种效果。

6 个答案:

答案 0 :(得分:14)

在构建抽屉之前,使用precacheImage函数开始加载图像。例如,在包含抽屉的小部件中:

class MyWidgetState extends State<MyWidget> {

  @override
  void initState() {
    // adjust the provider based on the image type
    precacheImage(new AssetImage('...'));
    super.initState();
  }

}

答案 1 :(得分:6)

关于这个主题有一篇很好的文章:https://alex.domenici.net/archive/preload-images-in-a-stateful-widget-on-flutter

它应该看起来像这样

class _SampleWidgetState extends State<SampleWidget> {
  Image image1;
  Image image2;
  Image image3;
  Image image4;

  @override
  void initState() {
    super.initState();

    image1 = Image.asset("assets/image1.png");
    image2 = Image.asset("assets/image2.png");
    image3 = Image.asset("assets/image3.png");
    image4 = Image.asset("assets/image4.png");
  }

  @override
  void didChangeDependencies() {
    super.didChangeDependencies();

    precacheImage(image1.image, context);
    precacheImage(image2.image, context);
    precacheImage(image3.image, context);
    precacheImage(image4.image, context);
  }

  @override
  Widget build(BuildContext context) {
    return Container(
          child: Stack(
            children: <Widget>[
              image1,
              image2,
              image3,
              image4,
            ],
          ),
        );
  }
}

答案 2 :(得分:4)

precacheImage()函数(在大多数答案中使用)返回一个Future,对于某些用例场景,它确实非常有用。例如,在我的应用程序中,我需要加载外部图像,并且像其他所有人一样,不想经历闪烁。所以我最终得到了这样的东西:

// show some sort of loading indicator
...

precacheImage(
    NetworkImage(),
    context,
).then((_) {
    // replace the loading indicator and show the image
    // (may be with some soothing fade in effect etc.)
    ...
});

请注意,在上面的示例中,我想说明如何Future被潜在地使用。评论只是为了帮助表达想法。实际的实现必须以Fluttery的方式完成。

答案 3 :(得分:2)

要摆脱“闪烁”,您可以简单地将FadeInImage classtransparent_image结合使用,它们会褪色而不是立即出现。就您而言,用法如下:

// you need to add transparent_image to your pubspec and import it
// as it is required to have the actual image fade in from nothing
import 'package:transparent_image/transparent_image.dart';
import 'package:flutter/material.dart';

...
  FadeInImage(
    placeholder: MemoryImage(kTransparentImage),
    image: AssetImage('image.png'),
  )

答案 4 :(得分:1)

我遇到以下问题:图像需要一些空间。因此,加载后,它将UI推低,这对UX不利。我决定创建一个生成器以显示一个空的(或正在加载的)容器,直到图像加载完毕,然后再显示我的UI。

看起来像precacheImage返回的将来已解决。对我而言,最棘手的部分是FutureBuildersnapshot.hasData,它们始终是false,因为null解决了未来。因此,我添加了将来的转换以修复snapshot.hasData

precacheImage(this.widget.imageProvider, context).then((value) => true)

我不确定是否可以多次调用precacheImage,所以我决定将其包装到StatefulWidget中。

您可以检查最终的构建器here

通过以下方式使用构建器:

return PreloadingImageBuilder(
      imageProvider: AssetImage("assets/images/logo-main.png"),
      builder: (context, snapshot) {
        if (snapshot.hasData) {
          return Scaffold(
            ...
          );
        } else {
          return Container();
        }
      },
    );

答案 5 :(得分:0)

我在使用initState内部的precacheImage()的上层解决方案时遇到了问题。下面的代码解决了它们。另外请注意,在调试模式下可能看不到预期的结果,而在发布模式下则看不到预期的结果。

Image myImage;

  @override
  void initState() {
    super.initState();
    myImage= Image.asset(path);
  }

  @override
  void didChangeDependencies() {
    super.didChangeDependencies();
    precacheImage(myImage.image, context);
  }