如何在Flutter中使用precacheImage函数?

9

在Flutter中,无法使用precacheImage函数将本地图片从assets加载到GridView或ListView中进行缓存。

问题:当滚动列表时,图片总是重新加载。

class AppLandingPage extends StatelessWidget {
  final String title;

  AppLandingPage({Key key, this.title}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return Scaffold(
        drawer: DrawerPage(),
        body: NestedScrollView(
          headerSliverBuilder: (BuildContext context, bool innerBoxIsScrolled) {
            return getToolbarWidget("Home title");
          },
          body: setDataToContainer(),
        ));
  }
}

Container setDataToContainer() {
  return Container(
    color: Colors.white,
    margin: EdgeInsets.only(left: 4.0, right: 4, bottom: 4, top: 4),
    child: CustomScrollView(
      slivers: <Widget>[
        SliverList(
          delegate: SliverChildListDelegate(
            [
              HeaderWidget("Header 1"),
            ],
          ),
        ),
        SliverGrid(
          gridDelegate:
          SliverGridDelegateWithFixedCrossAxisCount(crossAxisCount: 2),
          delegate: SliverChildListDelegate(
            [
              BodyWidget("title", "key_x", "pnl.svg"),
              BodyWidget("title2", "key_x", "cls.svg"),
              BodyWidget(
                  "title3", "key_x", "irr.svg"),
              BodyWidget(
                  "title4", "key_x", "icp.svg"),
            ],
          ),
        ),
        SliverList(
          delegate: SliverChildListDelegate(
            [
              HeaderWidget("Header 2"),
            ],
          ),
        ),
        SliverGrid(
          gridDelegate:
          SliverGridDelegateWithFixedCrossAxisCount(crossAxisCount: 2),
          delegate: SliverChildListDelegate(
            [
              BodyWidget("title5", "key_x", "ict.svg"),
              BodyWidget("title6", "key_x", "icc.svg"),
            ],
          ),
        ),
        SliverList(
          delegate: SliverChildListDelegate(
            [
              HeaderWidget("Others"),
            ],
          ),
        ),
        SliverGrid(
          gridDelegate:
          SliverGridDelegateWithFixedCrossAxisCount(crossAxisCount: 2),
          delegate: SliverChildListDelegate(
            [
              BodyWidget("title7", "key_x", "icd.svg"),
              BodyWidget("title8", "6", "ici.svg"),
            ],
          ),
        ),
      ],
    ),
  );
}

class HeaderWidget extends StatelessWidget {
  final String text;

  HeaderWidget(this.text);

  @override
  Widget build(BuildContext context) {
    return Container(
      padding: EdgeInsets.only(left: 10.0, right: 10, bottom: 2, top: 20),
      child: Text(
        text.toUpperCase(),
        style: TextStyle(
            color: hexToColor(themeColor1),
            fontSize: 16,
            fontWeight: FontWeight.bold),
      ),
      color: Colors.white,
    );
  }
}

class BodyWidget extends StatelessWidget {
  final String imagePath;
  final String title;
  final String navigationKey;

  BodyWidget(this.title, this.navigationKey, this.imagePath);

  @override
  Widget build(BuildContext context) {
    return Container(
        alignment: Alignment.center,
        child: Card(
          color: hexToColor(themeColor1),
          elevation: 5,
          child: InkWell(
            onTap: () {
              navigateToView(context, navigationKey);
            },
            child: Stack(
              children: <Widget>[
                Align(
                  alignment: Alignment.topCenter,
                  child: Container(
                    margin: EdgeInsets.only(top: 40),
                    child: SvgPicture.asset(
                      "assets/images/$imagePath",
                      color: Colors.white,
                      width: 35,
                      height: 35,
                    ),
                  ),
                ),
                Align(
                  alignment: Alignment.bottomCenter,
                  child: Column(
                    crossAxisAlignment: CrossAxisAlignment.stretch,
                    verticalDirection: VerticalDirection.up,
                    children: <Widget>[
                      Container(
                        padding: EdgeInsets.all(10),
                        color: Colors.black.withOpacity(.2),
                        child: Text(
                          title,
                          style: TextStyle(
                              color: Colors.white,
                              fontSize: 14,
                              fontWeight: FontWeight.normal),
                        ),
                      )
                    ],
                  ),
                ),
              ],
            ),
          ),
        ));
  }

  void navigateToView(BuildContext context, String navigationKey) {

    Navigator.push(
      context,
      PageRouteBuilder(
        pageBuilder: (context, animation1, animation2) {
          return NewSections();
        },
        transitionsBuilder: (context, animation1, animation2, child) {
          return FadeTransition(
            opacity: animation1,
            child: child,
          );
        },
        transitionDuration: Duration(milliseconds: 600),
      ),
    );
  }
}

发布你的代码。 - pskink
你的代码中没有使用precacheImage - pskink
在_TemplatesState.initState()完成之前调用了inheritFromWidgetOfExactType(MediaQuery)或inheritFromElement()。 当继承的widget发生变化时,例如Theme.of()的值发生变化,其依赖的widget将被重建。如果依赖widget对继承widget的引用位于构造函数或initState()方法中,则重建的依赖widget将不会反映继承widget中的更改。通常情况下,对继承widget的引用应出现在widget build()方法中。 - jazzbpn
3
https://alex.domenici.net/archive/preload-images-in-a-stateful-widget-on-flutter - pskink
尝试使用precacheImage()函数返回的FutureFutureBuilder一起使用了吗? - pskink
显示剩余6条评论
2个回答

11

不要在initState()中调用precacheImage(),应该像这样进行:

Image myImage;

@override
void initState() {
  super.initState();
  myImage= Image.asset(path);
}
  
@override
void didChangeDependencies() {
  super.didChangeDependencies();
  precacheImage(myImage.image, context);
}

2
我不确定如何解决预加载的问题。但是,您可以在Stateful Widget的状态类中(包含网格对象的类)使用AutomaticKeepAliveClientMixin,这样您只需加载每个图像一次,而不会在小部件不可见时重新渲染。请确保将BodyWidget设置为StatefulWidget。"Original Answer"翻译成"最初的回答"。
class _WidgetState extends State<Widget> with AutomaticKeepAliveClientMixin<Widget>{
….
….
@override
@mustCallSuper
Widget build(BuildContext context)….
….
….
@override
bool get wantKeepAlive => true;
}'

希望这能帮到你!最初的回答。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接