flutter - 使用 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
}
});
}),
)
],
),
),
),
);
}
}
解决方案
我的抽屉背景图像也有同样的问题,我用预缓存图像解决了这个问题,我猜你在错误的地方使用了预缓存图像。您需要了解,为了正确显示图像,您需要在应用程序启动时加载图像,而不是直到状态启动。尝试这个:
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");
推荐阅读
- css - 在线性梯度上使用具有背景位置的百分比值
- c# - 返回多个连接/导航对象
- kubernetes - 无法从 pod 中抓取指标
- java - 找不到存在于 java 中的图像文件
- php - 删除/禁用 Wordpress 日期和 /blog 链接
- r - 在 R 中选择每个日期每个 ID 的第一个正匹配
- android - 使用 Glide 检索时图像变得模糊
- python - 错误预期类型 StringIO,改为 str
- c# - 当 IsSelected 时 WPF DataGrid 设置文本换行
- cordova - 无法解析配置“:app:debugCompileClasspath”的所有文件