首页 > 解决方案 > 使用 Flutter 加载非常简单的图像非常慢

问题描述

我正在使用 Flutter SDK 和 Dart 制作一个移动应用程序,到目前为止,我只得到了一个简单的用户登录表单,上面的主要小部件是一个 ListView,顶部小部件作为 Card 小部件,内部有一个图像作为logo,我的问题是,这个 logo 需要 1 到 2 秒才能加载,而且看起来很丑,我的意思是,当我启动应用程序时,在启动屏幕之后,我在 Card 小部件上看到的只是一个空白区域,之后我的图像出现 1 到 2 秒,非常明显。

我阅读了很多避免这种情况的方法,但似乎都没有,最常见的是使用 precacheImage 方法来预加载图像,但这似乎不起作用,我也在构建时尝试了这个,同样的事情发生了,我必须澄清这个标志的大小非常小(100kB)。

到目前为止,这是我的代码的一部分,这个 HomeState 类只是 Home 有状态小部件的状态,它是作为 MaterialApp 主页的 Scaffold 小部件的主体,这是主屏幕,所以在启动屏幕之后这是加载的第一件事,

class HomeState extends State<Home> {
  var _minPad = 5.0;
  var _formKey = GlobalKey<FormState>();
  TextEditingController username = TextEditingController();
  TextEditingController password = TextEditingController();
  ImageProvider logo;

  @override
  void didChangeDependencies() async {
    logo = AssetImage('images/logo_rienpa.png');
    await precacheImage(logo, context);
    super.didChangeDependencies();
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
          title: Center(
              child: Text('Rutinas de Mantenimiento',
                  textAlign: TextAlign.center))),
      body: loginForm(),
      backgroundColor: Colors.blue,
    );
  }

  Form loginForm() {
    TextStyle titleStyle = Theme.of(context).textTheme.title;
    return Form(
        key: _formKey,
        child: Padding(
          padding: EdgeInsets.all(_minPad * 4),
          child: Center(
            child: ListView(
              children: <Widget>[
                getLogo(),
                Padding(
                    padding:
                        EdgeInsets.only(top: _minPad * 8, bottom: _minPad * 2),
                    child: TextFormField(
                      controller: username,
                      keyboardType: TextInputType.text,
                      style: titleStyle,
                      validator: (String value) {
                        if (value.isEmpty) {
                          return 'Por favor, ingresa tu nombre de usuario';
                        }
                      },
                      decoration: InputDecoration(
                          labelText: 'Usuario',
                          labelStyle: titleStyle,
                          hintText: 'Ingresa tu usuario',
                          border: OutlineInputBorder(
                              borderRadius: BorderRadius.circular(5.0))),
                    )),
                Padding(
                  padding:
                      EdgeInsets.only(top: _minPad * 2, bottom: _minPad * 4),
                  child: TextFormField(
                    controller: password,
                    obscureText: true,
                    style: titleStyle,
                    validator: (String value) {
                      if (value.isEmpty) {
                        return 'Por favor, ingresa una contraseña';
                      }
                    },
                    decoration: InputDecoration(
                        labelText: 'Contraseña',
                        labelStyle: titleStyle,
                        hintText: 'Contraseña personal',
                        border: OutlineInputBorder(
                            borderRadius: BorderRadius.circular(5.0))),
                  ),
                ),
                Padding(
                  padding: EdgeInsets.only(
                      top: _minPad * 2,
                      bottom: _minPad * 2,
                      right: _minPad * 20,
                      left: _minPad * 20),
                  child: RaisedButton(
                      color: Theme.of(context).primaryColor,
                      textColor: Colors.white,
                      child: Text(
                        "Ingresar",
                        textScaleFactor: 1.5,
                      ),
                      onPressed: () {
                        setState(() {
                          if (_formKey.currentState.validate()) {
                            //code
                          }
                        });
                      }),
                ),
                Padding(
                    padding:
                        EdgeInsets.only(top: _minPad * 10, bottom: _minPad * 2),
                    child: Row(
                      mainAxisAlignment: MainAxisAlignment.center,
                      children: <Widget>[
                        Text(
                          "No tienes un usuario?, registrate ",
                          textAlign: TextAlign.center,
                          style: TextStyle(color: Colors.white),
                        ),
                        InkWell(
                          child: Text(
                            'aqui',
                            textAlign: TextAlign.center,
                            style: TextStyle(
                                color: Colors.black,
                                decoration: TextDecoration.underline),
                          ),
                          onTap: () {
                            Navigator.push(context,
                                MaterialPageRoute(builder: (context) {
                              return Register();
                            }));
                          },
                        ),
                        Text(
                          ".",
                          textAlign: TextAlign.center,
                          style: TextStyle(color: Colors.white),
                        )
                      ],
                    ))
              ],
            ),
          ),
        ));
  }

  Widget getLogo() {
    Image logoImage = Image(image: logo, width: 250.0, height: 167.0,);
    return Padding(
        padding: EdgeInsets.only(right: _minPad * 5, left: _minPad * 5),
        child: Card(
          color: Colors.white,
          elevation: 8.0,
          child: logoImage,
          shape:
              RoundedRectangleBorder(borderRadius: BorderRadius.circular(30.0)),
        ));
  }
}

更新

根据要求,这是我的完整代码,它们是三个文件。

主要飞镖:

import 'package:flutter/material.dart';
import 'package:rutinas_de_mantenimiento/screens/home.dart';

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

class MainApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    precacheImage(AssetImage('images/logo_rienpa.png'), context);
    return MaterialApp(
      title: "Rutinas de Mantenimiento",
      debugShowCheckedModeBanner: false,
      theme: ThemeData(
          primarySwatch: Colors.blueGrey, primaryColor: Colors.blueGrey),
      home: Home(),
    );
  }
}

home.dart(加载图片的地方)

import 'package:flutter/material.dart';
import 'package:rutinas_de_mantenimiento/screens/register.dart';

class Home extends StatefulWidget {
  @override
  State<StatefulWidget> createState() {
    return HomeState();
  }
}

class HomeState extends State<Home> {
  var _minPad = 5.0;
  var _formKey = GlobalKey<FormState>();
  TextEditingController username = TextEditingController();
  TextEditingController password = TextEditingController();
  ImageProvider logo = AssetImage('images/logo_rienpa.png');

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
          title: Center(
              child: Text('Rutinas de Mantenimiento',
                  textAlign: TextAlign.center))),
      body: loginForm(),
      backgroundColor: Colors.blue,
    );
  }

  Form loginForm() {
    TextStyle titleStyle = Theme.of(context).textTheme.title;
    return Form(
        key: _formKey,
        child: Padding(
          padding: EdgeInsets.all(_minPad * 4),
          child: Center(
            child: ListView(
              children: <Widget>[
                getLogo(),
                Padding(
                    padding:
                        EdgeInsets.only(top: _minPad * 8, bottom: _minPad * 2),
                    child: TextFormField(
                      controller: username,
                      keyboardType: TextInputType.text,
                      style: titleStyle,
                      validator: (String value) {
                        if (value.isEmpty) {
                          return 'Por favor, ingresa tu nombre de usuario';
                        }
                      },
                      decoration: InputDecoration(
                          labelText: 'Usuario',
                          labelStyle: titleStyle,
                          hintText: 'Ingresa tu usuario',
                          border: OutlineInputBorder(
                              borderRadius: BorderRadius.circular(5.0))),
                    )),
                Padding(
                  padding:
                      EdgeInsets.only(top: _minPad * 2, bottom: _minPad * 4),
                  child: TextFormField(
                    controller: password,
                    obscureText: true,
                    style: titleStyle,
                    validator: (String value) {
                      if (value.isEmpty) {
                        return 'Por favor, ingresa una contraseña';
                      }
                    },
                    decoration: InputDecoration(
                        labelText: 'Contraseña',
                        labelStyle: titleStyle,
                        hintText: 'Contraseña personal',
                        border: OutlineInputBorder(
                            borderRadius: BorderRadius.circular(5.0))),
                  ),
                ),
                Padding(
                  padding: EdgeInsets.only(
                      top: _minPad * 2,
                      bottom: _minPad * 2,
                      right: _minPad * 20,
                      left: _minPad * 20),
                  child: RaisedButton(
                      color: Theme.of(context).primaryColor,
                      textColor: Colors.white,
                      child: Text(
                        "Ingresar",
                        textScaleFactor: 1.5,
                      ),
                      onPressed: () {
                        setState(() {
                          if (_formKey.currentState.validate()) {
                            //code
                          }
                        });
                      }),
                ),
                Padding(
                    padding:
                        EdgeInsets.only(top: _minPad * 10, bottom: _minPad * 2),
                    child: Row(
                      mainAxisAlignment: MainAxisAlignment.center,
                      children: <Widget>[
                        Text(
                          "No tienes un usuario?, registrate ",
                          textAlign: TextAlign.center,
                          style: TextStyle(color: Colors.white),
                        ),
                        InkWell(
                          child: Text(
                            'aqui',
                            textAlign: TextAlign.center,
                            style: TextStyle(
                                color: Colors.black,
                                decoration: TextDecoration.underline),
                          ),
                          onTap: () {
                            Navigator.push(context,
                                MaterialPageRoute(builder: (context) {
                              return Register();
                            }));
                          },
                        ),
                        Text(
                          ".",
                          textAlign: TextAlign.center,
                          style: TextStyle(color: Colors.white),
                        )
                      ],
                    ))
              ],
            ),
          ),
        ));
  }

  Widget getLogo() {
    Image logoImage = Image(image: logo, width: 250.0, height: 167.0,);
    return Padding(
        padding: EdgeInsets.only(right: _minPad * 5, left: _minPad * 5),
        child: Card(
          color: Colors.white,
          elevation: 8.0,
          child: logoImage,
          shape:
              RoundedRectangleBorder(borderRadius: BorderRadius.circular(30.0)),
        ));
  }
}

而 resgister.dart 我认为这不是必需的,但它就在这里

import 'package:flutter/material.dart';

class Register extends StatefulWidget {
  @override
  State<StatefulWidget> createState() {
    return RegisterState();
  }
}

class RegisterState extends State<Register> {
  var _formKey = GlobalKey<FormState>();
  TextEditingController fullName = TextEditingController();
  TextEditingController username = TextEditingController();
  TextEditingController password = TextEditingController();
  TextEditingController confirmPwd = TextEditingController();
  TextEditingController email = TextEditingController();

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Center(
          child: Text(
            'Rutinas de Mantenimiento',
            textAlign: TextAlign.center,
          ),
        ),
        automaticallyImplyLeading: false,
      ),
      body: registerForm(),
      backgroundColor: Colors.blue,
    );
  }

  Form registerForm() {
    var _minPad = 5.0;
    TextStyle titleStyle = Theme.of(context).textTheme.title;

    return Form(
      key: _formKey,
      child: Padding(
        padding: EdgeInsets.all(_minPad * 4),
        child: Center(
          child: ListView(
            children: <Widget>[
              Text(
                "Registro de usuario",
                textAlign: TextAlign.center,
                style: TextStyle(
                    decoration: null,
                    fontSize: 35.0,
                    color: Colors.white),
              ),
              Padding(
                padding:
                EdgeInsets.only(top: _minPad * 14, bottom: _minPad * 2),
                child: TextFormField(
                  controller: fullName,
                  style: titleStyle,
                  textAlign: TextAlign.center,
                  validator: (String value) {
                    if (value.isEmpty) {
                      return 'Por favor ingresa tu nombre completo';
                    }
                  },
                  decoration: InputDecoration(
                      hintText: "Nombre completo", hintStyle: titleStyle),
                ),
              ),
              Padding(
                padding: EdgeInsets.only(top: _minPad * 2, bottom: _minPad * 2),
                child: TextFormField(
                  controller: username,
                  style: titleStyle,
                  textAlign: TextAlign.center,
                  validator: (String value) {
                    if (value.isEmpty) {
                      return 'Por favor ingresa un usuario';
                    }
                  },
                  decoration: InputDecoration(
                      hintText: "Nombre de usuario", hintStyle: titleStyle),
                ),
              ),
              Padding(
                padding: EdgeInsets.only(top: _minPad * 2, bottom: _minPad * 2),
                child: TextFormField(
                  controller: email,
                  style: titleStyle,
                  textAlign: TextAlign.center,
                  validator: (String value) {
                    if (value.isEmpty) {
                      return 'Por favor ingresa tu Email';
                    }
                  },
                  decoration:
                  InputDecoration(hintText: "Email", hintStyle: titleStyle),
                ),
              ),
              Padding(
                padding: EdgeInsets.only(top: _minPad * 2, bottom: _minPad * 2),
                child: TextFormField(
                  controller: password,
                  obscureText: true,
                  style: titleStyle,
                  textAlign: TextAlign.center,
                  validator: (String value) {
                    if (value.isEmpty) {
                      return 'Por favor ingresa una contraseña';
                    }
                  },
                  decoration: InputDecoration(
                      hintText: "Contraseña", hintStyle: titleStyle),
                ),
              ),
              Padding(
                padding: EdgeInsets.only(top: _minPad * 2, bottom: _minPad * 2),
                child: TextFormField(
                  controller: confirmPwd,
                  obscureText: true,
                  style: titleStyle,
                  textAlign: TextAlign.center,
                  validator: (String value) {
                    if (value.isEmpty) {
                      return 'Por favor repita su contraseña';
                    }
                  },
                  decoration: InputDecoration(
                      hintText: "Confirme contraseña", hintStyle: titleStyle),
                ),
              ),
              Padding(
                padding: EdgeInsets.only(
                    top: _minPad * 4,
                    bottom: _minPad * 2,
                    right: _minPad * 20,
                    left: _minPad * 20),
                child: RaisedButton(
                    color: Theme.of(context).primaryColor,
                    textColor: Colors.white,
                    child: Text(
                      "Registrar",
                      textScaleFactor: 1.5,
                    ),
                    onPressed: () {
                      setState(() {
                        if (_formKey.currentState.validate()) {
                          //code
                        }
                      });
                    }),
              )
            ],
          ),
        ),
      ),
    );
  }
}

标签: flutterdart

解决方案


我的抽屉背景图像也有同样的问题,我用预缓存图像解决了这个问题,我猜你在错误的地方使用了预缓存图像。您需要了解,为了正确显示图像,您需要在应用程序启动时加载图像,而不是直到状态启动。尝试这个:

 class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    precacheImage(AssetImage("images/logo_rienpa.png"), context);
    return MaterialApp(
      title: 'Fethi',
      theme: ThemeData(
        primarySwatch: Colors.lightBlue,
      ),
      home: new HomeState(),
    );
  }
}

在 HomeState 页面上,您不需要使用 didChangeDependencies(),只需在定义中声明图像,如下所示:

 ImageProvider logo = AssetImage("images/logo_rienpa.png");

推荐阅读