Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Very simple image loaded pretty slow with Flutter

Tags:

flutter

dart

I'm making a mobile application using the Flutter SDK and Dart, so far, I just got a simple User login form, the main widget over that is a ListView with the top widget as a Card widget with an image inside that works as a logo, my problem is, this logo takes like 1 to 2 seconds to load, and looks very ugly, I mean, when I launch the app, after the splash screen, all I see over my Card widget is a blank space, and after 1 to 2 seconds my image appears, it is very noticeable.

I read many ways to avoid this but none seem to work, the most common is to use precacheImage method to preload the image but that doesn't seem to work, I also tried this over the built as release and same thing happen, I must clarify that this logo is very small in size (100kB).

So far this is a part of my code, this HomeState class is just State of the Home stateful widget that is the body of a Scaffold widget that is the home of a MaterialApp, this is the main screen, so after the splash screen this is the first thing that loads,

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)),
        ));
  }
}

UPDATE

As requested, here is my full code, they are three files.

main.dart:

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 (place where the image is loaded)

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)),
        ));
  }
}

And resgister.dart I think this is not needed but here it goes

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
                        }
                      });
                    }),
              )
            ],
          ),
        ),
      ),
    );
  }
}
like image 420
Ronald Petit Avatar asked Jun 03 '19 20:06

Ronald Petit


People also ask

How do I make my pictures load faster on Flutter?

We have a simple yet useful method in Flutter which we can use to load our asset images much faster — precacheImage()! This method good the image into the image cache and then whenever the image is used, it will be loaded much faster. However, Image Cache doesn't allow to hold very large images.

How do you lazy load images on Flutter?

First, you need to add cached_network_image Flutter package in your project by adding following lines in pubspec. yaml file. Cached_network_image both caching and lazy loading while scrolling on your app. The images under the view will not get loaded untill it comes to screen view on scroll.

How can I improve my fluttering performance?

Decrease Application Size With the help of Gradle, you can reduce the Flutter application size to optimize Flutter performance. Using the packaging system introduced by Google, you can create bundles of Android applications. App Bundles are beneficial in many ways.


1 Answers

I had the same problem with my drawer background image and I solved it with the precache Image, i guess you are using the precacheimage on the wrong place. you need to understand that in order to show the image correctly you need to load the image on app start and not till the state is initiated. try this:

 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(),
    );
  }
}

On the HomeState page you don't need to use didChangeDependencies(), just declare the image on the definition like this :

 ImageProvider logo = AssetImage("images/logo_rienpa.png");
like image 98
Fethi Avatar answered Nov 18 '22 17:11

Fethi