0
votes

I'm trying to make a splash screen for my Flutter application. I want my logo to rotate while checking if the user is logged on firebase authentifaction and then going to the views concerned depending of the return value.

The problem is that my application doesn't build properly before my async call (I see my backGround but not the AnimatedBuilder).

I tried running my CheckUser() using the after_layout package, or using this function :

WidgetsBinding.instance.addPostFrameCallback((_) => yourFunction(context));

but it always wait for the CheckUser() function to finish so I don't see the animation as it navigates directly to my other views.

Here's my code if you want to test it :

import 'dart:io';

import 'package:flutter/material.dart';
import 'package:firebase_auth/firebase_auth.dart';
import 'package:skull_mobile/connexion/login.dart';
import 'accueil.dart';

class SplashPage extends StatefulWidget {
  SplashPage({Key key}) : super(key: key);

  @override
  _SplashPage createState() => _SplashPage();
}

class _SplashPage extends State<SplashPage>
    with SingleTickerProviderStateMixin {

  AnimationController animationController;

  @override
  void initState() {
    super.initState();
    animationController = new AnimationController(
      vsync: this,
      duration: new Duration(seconds: 5),
    );
    animationController.repeat();
    checkUser();
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      backgroundColor: Colors.grey[800],
      body: Center(
        child: Container(
          child: new AnimatedBuilder(
            animation: animationController,
            child: new Container(
              height: 150.0,
              width: 150.0,
              child: new Image.asset('assets/skull.png'),
            ),
            builder: (BuildContext context, Widget _widget) {
              return new Transform.rotate(
                angle: animationController.value * 6.3,
                child: _widget,
              );
            },
          ),
        ),
      ),
    );
  }

  void checkUser() async {
    FirebaseAuth.instance.currentUser().then((currentUser) => {
          if (currentUser == null)
            {Navigator.pushNamed(context, LoginPage.routeName)}
          else
            {Navigator.pushNamed(context, AccueilPage.routeName)}
        });
  }
}
1
The screen first needs to be created, then check anything. Try to use a FutureBuilder, as this firebase function is a Future <FirebaseUser>. And remove it from initeState, calling it through FutureBuilder. - Edeson Bizerril
Have you attempted separating these into different widgets? Have your main app file load and display the splash widget with its animation while at the same time making the request you need. Once the request is finished you can either replace the splash widget with the screen you want to show, or navigate to another view. - João Soares

1 Answers

0
votes

Following on my comment I'm sharing here a snippet of my own code and how I handle a splash screen, here called "WaitingScreen", the device's Connection state and then send the user to different pages with different properties depending on the results:

@override
Widget build(BuildContext context) {
  switch (authStatus) {
    case AuthStatus.notDetermined:
      if(_connectionStatus == ConnectionStatus.connected){
        return _buildWaitingScreen();
      }else{
        return _buildNoConnectionScreen();
      }
      break;
    case AuthStatus.notSignedIn:
      return LoginPage(
        onSignedIn: _signedIn,
        setThemePreference: widget.setThemePreference,
      );
    case AuthStatus.signedIn:
      return MainPage(
        onSignedOut: _signedOut,
        setThemePreference: widget.setThemePreference,
        getThemePreference: widget.getThemePreference,
      );
  }
  return null;
}