在构建之前预加载资产图像

Posted

技术标签:

【中文标题】在构建之前预加载资产图像【英文标题】:preload assets images before build 【发布时间】:2019-04-18 08:36:34 【问题描述】:

我正在尝试将我的容器的背景图像设置为来自以下资产的图像:

return new Container(
            decoration: new BoxDecoration(
              image: new DecorationImage(
                image: new AssetImage(images[index]),
                fit: BoxFit.cover,
              ),
            ),

但这需要一些时间来加载并返回空白屏幕直到图像加载..

所以我尝试像这样在构建之前预加载图像:

@override
void initState() 
precacheImage(new AssetImage(images[1]), context);
precacheImage(new AssetImage(images[2]), context);
precacheImage(new AssetImage(images[3]), context);
super.initState();

这返回了这个错误:

颤振:══╡小部件库发现异常╞═══════════════════════════════════════════ ═══════════════════════ 颤振:在构建 Builder 时抛出了以下断言: 颤振:之前调用了inheritFromWidgetOfExactType(MediaQuery) 或inheritFromElement() 颤振:_WalkthroughPageState.initState() 完成。 Flutter:当继承的小部件发生变化时,例如如果 Theme.of() 的值发生变化,它的依赖 颤振:小部件被重建。如果依赖小部件对继承小部件的引用在构造函数中 flutter: 或 initState() 方法,那么重建的依赖小部件将不会反映 颤振:继承的小部件。 颤振:通常对继承的小部件的引用应该出现在小部件的 build() 方法中。或者, flutter:基于继承的widget的初始化可以放在didChangeDependencies方法中, flutter: 在 initState 之后以及此后依赖项发生变化时调用。 扑: 颤振:抛出异常时,这是堆栈: 颤振:#0 StatefulElement.inheritFromElement。 (包:flutter/src/widgets/framework.dart:3898:9) 颤振:#1 StatefulElement.inheritFromElement(包:flutter/src/widgets/framework.dart:3931:6) 颤振:#2 Element.inheritFromWidgetOfExactType (package:flutter/src/widgets/framework.dart:3274:14) 颤振:#3 MediaQuery.of(包:flutter/src/widgets/media_query.dart:476:38) 颤振:#4 createLocalImageConfiguration(包:flutter/src/widgets/image.dart:49:34) 颤振:#5 precacheImage(包:颤振/src/widgets/image.dart:81:37) 颤振:#6 _WalkthroughPageState.initState(包:spl/Pages/walkthrough.page.dart:65:5) 颤振:#7 StatefulElement._firstBuild(包:flutter/src/widgets/framework.dart:3808:58) 颤振:#8 ComponentElement.mount(包:颤振/src/widgets/framework.dart:3674:5) 颤振:#9 Element.inflateWidget(包:flutter/src/widgets/framework.dart:2950:14) 颤振:#10 Element.updateChild(包:颤振/src/widgets/framework.dart:2753:12) 颤振:#11 ComponentElement.performRebuild(包:颤振/src/widgets/framework.dart:3710:16) 颤振:#12 Element.rebuild(包:颤振/src/widgets/framework.dart:3547:5) 颤振:#13 ComponentElement._firstBuild(包:颤振/src/widgets/framework.dart:3679:5) 颤振:#14 ComponentElement.mount(包:颤振/src/widgets/framework.dart:3674:5) 颤振:#15 Element.inflateWidget(包:flutter/src/widgets/framework.dart:2950:14) 颤振:#16 Element.updateChild(包:颤振/src/widgets/framework.dart:2753:12) 颤振:#17 SingleChildRenderObjectElement.mount(包:flutter/src/widgets/framework.dart:4838:14) 颤振:#18 Element.inflateWidget(包:flutter/src/widgets/framework.dart:2950:14) 颤振:#19 Element.updateChild(包:flutter/src/widgets/framework.dart:2753:12) 颤振:#20 SingleChildRenderObjectElement.mount(包:颤振/src/widgets/framework.dart:4838:14) 颤振:#21 Element.inflateWidget(包:flutter/src/widgets/framework.dart:2950:14) 颤振:#22 Element.updateChild(包:flutter/src/widgets/framework.dart:2753:12) 颤振:#23 SingleChildRenderObjectElement.mount(包:flutter/src/widgets/framework.dart:4838:14) 颤振:#24 Element.inflateWidget(包:flutter/src/widgets/framework.dart:2950:14) 颤振:#25 Element.updateChild(包:颤振/src/widgets/framework.dart:2753:12) 颤振:#26 ComponentElement.performRebuild(包:颤振/src/widgets/framework.dart:3710:16) 颤振:#27 Element.rebuild(包:颤振/src/widgets/framework.dart:3547:5) 颤振:#28 ComponentElement._firstBuild(包:颤振/src/widgets/framework.dart:3679:5) 颤振:#29 StatefulElement._firstBuild(包:flutter/src/widgets/framework.dart:3826:11) 颤振:#30 ComponentElement.mount (package:flutter/src/widgets/framework.dart:3674:5) 颤振:#31 Element.inflateWidget(包:flutter/src/widgets/framework.dart:2950:14) 颤振:#32 Element.updateChild(包:flutter/src/widgets/framework.dart:2753:12) 颤振:#33 SingleChildRenderObjectElement.mount(包:flutter/src/widgets/framework.dart:4838:14) 颤振:#34 Element.inflateWidget(包:flutter/src/widgets/framework.dart:2950:14) 颤振:#35 Element.updateChild(包:颤振/src/widgets/framework.dart:2753:12) 颤振:#36 ComponentElement.performRebuild(包:颤振/src/widgets/framework.dart:3710:16) 颤振:#37 Element.rebuild(包:颤振/src/widgets/framework.dart:3547:5) 颤振:#38 ComponentElement._firstBuild (package:flutter/src/widgets/framework.dart:3679:5) 颤振:#39 ComponentElement.mount(包:颤振/src/widgets/framework.dart:3674:5) 颤振:#40 Element.inflateWidget(包:flutter/src/widgets/framework.dart:2950:14) 颤振:#41 Element.updateChild(包:颤振/src/widgets/framework.dart:2753:12) 颤振:#42 SingleChildRenderObjectElement.mount(包:颤振/src/widgets/framework.dart:4838:14) 颤振:#43 Element.inflateWidget(包:flutter/src/widgets/framework.dart:2950:14) 颤振:#44 Element.updateChild(包:颤振/src/widgets/framework.dart:2753:12) 颤振:#45 ComponentElement.performRebuild(包:颤振/src/widgets/framework.dart:3710:16) 颤振:#46 Element.rebuild(包:颤振/src/widgets/framework.dart:3547:5) 颤振:#47 ComponentElement._firstBuild(包:颤振/src/widgets/framework.dart:3679:5) 颤振:#48 StatefulElement._firstBuild(包:flutter/src/widgets/framework.dart:3826:11) 颤振:#49 ComponentElement.mount (package:flutter/src/widgets/framework.dart:3674:5) 颤振:#50 Element.inflateWidget(包:flutter/src/widgets/framework.dart:2950:14) 颤振:#51 Element.updateChild(包:flutter/src/widgets/framework.dart:2753:12) 颤振:#52 ComponentElement.performRebuild(包:颤振/src/widgets/framework.dart:3710:16) 颤振:#53 Element.rebuild(包:颤振/src/widgets/framework.dart:3547:5) 颤振:#54 ComponentElement._firstBuild(包:颤振/src/widgets/framework.dart:3679:5) 颤振:#55 ComponentElement.mount(包:颤振/src/widgets/framework.dart:3674:5) 颤振:#56 Element.inflateWidget(包:flutter/src/widgets/framework.dart:2950:14) 颤振:#57 Element.updateChild(包:flutter/src/widgets/framework.dart:2753:12) 颤振:#58 SingleChildRenderObjectElement.mount(包:flutter/src/widgets/framework.dart:4838:14) 颤振:#59 Element.inflateWidget(包:flutter/src/widgets/framework.dart:2950:14) 颤振:#60 Element.updateChild(包:颤振/src/widgets/framework.dart:2753:12) 颤振:#61 ComponentElement.performRebuild(包:颤振/src/widgets/framework.dart:3710:16) 颤振:#62 Element.rebuild(包:颤振/src/widgets/framework.dart:3547:5) 颤振:#63 ComponentElement._firstBuild(包:flutter/src/widgets/framework.dart:3679:5) 颤振:#64 ComponentElement.mount(包:颤振/src/widgets/framework.dart:3674:5) 颤振:#65 Element.inflateWidget(包:flutter/src/widgets/framework.dart:2950:14) 颤振:#66 Element.updateChild(包:flutter/src/widgets/framework.dart:2753:12) 颤振:#67 ComponentElement.performRebuild(包:颤振/src/widgets/framework.dart:3710:16) 颤振:#68 Element.rebuild(包:颤振/src/widgets/framework.dart:3547:5) 颤振:#69 ComponentElement._firstBuild(包:颤振/src/widgets/framework.dart:3679:5) 颤振:#70 StatefulElement._firstBuild(包:flutter/src/widgets/framework.dart:3826:11) 颤振:#71 ComponentElement.mount(包:颤振/src/widgets/framework.dart:3674:5) 颤振:#72 Element.inflateWidget(包:flutter/src/widgets/framework.dart:2950:14) 颤振:#73 Element.updateChild(包:颤振/src/widgets/framework.dart:2753:12) 颤振:#74 ComponentElement.performRebuild(包:颤振/src/widgets/framework.dart:3710:16) 颤振:#75 Element.rebuild(包:颤振/src/widgets/framework.dart:3547:5) 颤振:#76 ComponentElement._firstBuild(包:颤振/src/widgets/framework.dart:3679:5) 颤振:#77 StatefulElement._firstBuild(包:flutter/src/widgets/framework.dart:3826:11) 颤振:#78 ComponentElement.mount(包:颤振/src/widgets/framework.dart:3674:5) 颤振:#79 Element.inflateWidget(包:flutter/src/widgets/framework.dart:2950:14) 颤振:#80 Element.updateChild(包:flutter/src/widgets/framework.dart:2753:12) 颤振:#81 RenderObjectElement.updateChildren(包:flutter/src/widgets/framework.dart:4621:32) 颤振:#82 MultiChildRenderObjectElement.update(包:flutter/src/widgets/framework.dart:4953:17) 颤振:#83 Element.updateChild(包:颤振/src/widgets/framework.dart:2742:15) 颤振:#84 _TheatreElement.update(包:颤振/src/widgets/overlay.dart:507:16) 颤振:#85 Element.updateChild(包:flutter/src/widgets/framework.dart:2742:15) 颤振:#86 ComponentElement.performRebuild(包:颤振/src/widgets/framework.dart:3710:16) 颤振:#87 Element.rebuild(包:颤振/src/widgets/framework.dart:3547:5) 颤振:#88 StatefulElement.update(包:flutter/src/widgets/framework.dart:3856:5) 颤振:#89 Element.updateChild(包:flutter/src/widgets/framework.dart:2742:15) 颤振:#90 ComponentElement.performRebuild(包:颤振/src/widgets/framework.dart:3710:16) 颤振:#91 Element.rebuild(包:颤振/src/widgets/framework.dart:3547:5) 颤振:#92 ProxyElement.update(包:颤振/src/widgets/framework.dart:3968:5) 颤振:#93 Element.updateChild(包:flutter/src/widgets/framework.dart:2742:15) 颤振:#94 SingleChildRenderObjectElement.update(包:flutter/src/widgets/framework.dart:4845:14) 颤振:#95 Element.updateChild(包:颤振/src/widgets/framework.dart:2742:15) 颤振:#96 ComponentElement.performRebuild(包:颤振/src/widgets/framework.dart:3710:16) 颤振:#97 Element.rebuild(包:颤振/src/widgets/framework.dart:3547:5) 颤振:#98 StatefulElement.update(包:flutter/src/widgets/framework.dart:3856:5) 颤振:#99 Element.updateChild(包:颤振/src/widgets/framework.dart:2742:15) 颤振:#100 SingleChildRenderObjectElement.update(包:flutter/src/widgets/framework.dart:4845:14) 颤振:#101 Element.updateChild(包:flutter/src/widgets/framework.dart:2742:15) 颤振:#102 SingleChildRenderObjectElement.update(包:颤振/src/widgets/framework.dart:4845:14) 颤振:#103 Element.updateChild(包:flutter/src/widgets/framework.dart:2742:15) 颤振:#104 ComponentElement.performRebuild(包:颤振/src/widgets/framework.dart:3710:16) 颤振:#105 Element.rebuild(包:颤振/src/widgets/framework.dart:3547:5) 颤振:#106 BuildOwner.buildScope(包:flutter/src/widgets/framework.dart:2286:33) 颤振:#107 _WidgetsFlutterBinding&BindingBase&GestureBinding&ServicesBinding&SchedulerBinding&PaintingBinding&SemanticsBinding&RendererBinding&WidgetsBinding.drawFrame(包:flutter/src/widgets/binding.dart:676:20) 颤振:#108 _WidgetsFlutterBinding&BindingBase&GestureBinding&ServicesBinding&SchedulerBinding&PaintingBinding&SemanticsBinding&RendererBinding._handlePersistentFrameCallback (package:flutter/src/rendering/binding.dart:219:5) 颤振:#109 _WidgetsFlutterBinding&BindingBase&GestureBinding&ServicesBinding&SchedulerBinding._invokeFrameCallback (package:flutter/src/scheduler/binding.dart:990:15) 颤振:#110 _WidgetsFlutterBinding&BindingBase&GestureBinding&ServicesBinding&SchedulerBinding.handleDrawFrame (package:flutter/src/scheduler/binding.dart:930:9) 颤振:#111 _WidgetsFlutterBinding&BindingBase&GestureBinding&ServicesBinding&SchedulerBinding._handleDrawFrame (package:flutter/src/scheduler/binding.dart:842:5) 颤振:#112 _invoke (dart:ui/hooks.dart:151:13) 颤振:#113 _drawFrame (dart:ui/hooks.dart:140:3) 颤抖:════════════════════════════════════════␕════␕═══════════ ══════════════════════════════════════════════════ ══

【问题讨论】:

【参考方案1】:

我遇到了同样的问题,解决方法在错误描述本身:

基于继承的小部件的初始化可以放在 didChangeDependencies 方法中,该方法在 initState 和 此后每当依赖关系发生变化时。

这是我的代码的简化版本,在方法 didChangeDependencies 中预加载图像:

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

  Image currentImage;

  @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");

    currentImage = image1;
  

  @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: currentImage,
    );
  

  void setImage(int index) 
      switch (index) 
        case 1: currentImage = image1; break;
        case 2: currentImage = image2; break;
        case 3: currentImage = image3; break;
        case 4: currentImage = image4; break;
      
  

希望这会有所帮助:)

【讨论】:

【参考方案2】:

我不确定,但我想,你可以试试FutureBuilder

import 'dart:ui' as ui;

class MyImage extends StatelessWidget 
  MyImage(this._imgSrc);
  final String _imgSrc;

  @override
  Widget build(BuildContext context) 
    Image image = Image.asset(_imgSrc);
    Completer<ui.Image> completer = new Completer<ui.Image>();
    image.image.resolve(ImageConfiguration()).addListener((ImageInfo info, bool _) 
      completer.complete(info.image);
    );
    return FutureBuilder(
        future: completer.future,
        builder: (context, AsyncSnapshot<ui.Image> snapshot) 
          return snapshot.hasData ? image : Container();
        );
  

【讨论】:

我收到了错误 ui,image is not a type can't be used as a type argument ... @lamatat import 'dart:ui' as ui; 好的,现在错误消失了..但我有三个图像..怎么办?我应该为每张图像重复三遍吗? 我想测试它,但我需要三个图像,这样我就可以在它们之间滑动,看看我的问题是否消失了.. @lamatat 以Future.wait 为例

以上是关于在构建之前预加载资产图像的主要内容,如果未能解决你的问题,请参考以下文章

为 CSS 动画预加载图像?

在按下 UIButton 之前预加载动画图像

使用链接中的预览图像预加载图像以提高性能

预加载音频文件/事件?

在 Animate CC 上添加预加载器

如何预加载网络工作者资产