Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

navigateAfterFuture called multiple times #55

Open
Akiat opened this issue Nov 26, 2020 · 6 comments
Open

navigateAfterFuture called multiple times #55

Akiat opened this issue Nov 26, 2020 · 6 comments

Comments

@Akiat
Copy link

Akiat commented Nov 26, 2020

First of all thank you for your great package.

The issue
The function assigned to navigateAfterFuture is called multiple times (2 or 3 times in my case).

The code

class MyApp extends StatefulWidget {
  @override
  _MyAppState createState() => new _MyAppState();
}

class _MyAppState extends State<MyApp> {
  MainSingleton mainSingleton = MainSingleton();

  @override
  Widget build(BuildContext context) {
    return SplashScreen(
        routeName: "/",
        navigateAfterFuture: loadFromFuture(),
        title: new Text(
          APP_NAME,
          style: new TextStyle(fontWeight: FontWeight.bold, fontSize: 30.0, color: Colors.green, fontFamily: "Roboto"),
        ),
        image: Image(image: AssetImage('assets/images/logo.png')),
    );
  }

  Future<Widget> loadFromFuture() async {
    await Firebase.initializeApp();
    // To catch background messages
    FirebaseMessaging.onBackgroundMessage(firebaseMessagingBackgroundHandler);
    FirebaseMessaging.onMessage.listen(firebaseMessagingForegroundHandler);
    String token = await FirebaseMessaging.instance.getToken();
    print("FirebaseMessaging token: $token");

    // These func only call my API to retreive some data.
    bool authorsLoaded = await loadAuthors();
    bool translatorsLoaded = await loadTranslators();
    bool tagsLoaded = await loadTags();
    bool captionsLoaded = await loadCaptions();

    return buildHomePage(authorsLoaded && translatorsLoaded && tagsLoaded && captionsLoaded);
  }

  Widget buildHomePage(bool everythingLoaded) {
    return MaterialApp(
      debugShowCheckedModeBanner: false,
      title: APP_NAME,
      theme: ThemeData(
        primarySwatch: Colors.green,
        visualDensity: VisualDensity.adaptivePlatformDensity,
      ),
      home: (everythingLoaded) ? HomePage() : buildRetryPage(),
    );
  }

Widget buildRetryPage() {
    return Scaffold(
      appBar: AppBar(title: Text(APP_NAME)),
      body: Container(
        child: Column(
          children: <Widget>[
            Text('PROBLEM, PLEASE RETRY'),
            Padding(padding: EdgeInsets.only(bottom: 20.0)),
            GFButton(
                text: "RETRY",
                onPressed: () async {
                  Navigator.of(context).pushReplacement(MaterialPageRoute(builder: (BuildContext context) => MyApp()));
                }),
          ],
        ),
      ),
    );
  }

Expected behavior
It should call my callback only one time, or I done something wrong.

Thanks for your help 👍

@diegodiaz22
Copy link

I am also experiencing the same

@ahmedmgh67
Copy link
Member

ahmedmgh67 commented Dec 13, 2020

That's weird
I can't reproduce it, temporarily you can make a variable that becomes true if the function ran and prevent the function from running again, but I will try to investigate it also
Thanks for reporting

@Akiat
Copy link
Author

Akiat commented Dec 13, 2020

Yes this is what I use to avoid multiple calls 👍

@kovacpetar
Copy link

I am also experiencing the same behaviour.
This is how it happens for me:

  Future<Widget> loadApplicationWithScreenToNavigate() async {
    printError(info: "Called");
    return Future.value(Home());
  }

  @override
  Widget build(BuildContext context) {
    return GetMaterialApp(
      title: 'Some title',
      debugShowCheckedModeBanner: false,
      theme: buildThemeData(),
      home: SplashScreen(
        navigateAfterFuture: loadApplicationWithScreenToNavigate(),
        backgroundColor: Colors.white,
    );

And in console I can see sometimes it's being called 2 times, sometimes 3 times.

P.S. Code above is pseudo code just to demonstrate the reproduction of this issue,

@kuromukira
Copy link

Probably that the state changes and redraws the widget thus calling your Future again 🤔

@MeyerMathieu
Copy link

MeyerMathieu commented Jun 29, 2021

I agree with @kuromukira , it should be a State issue.

A quick workaround worked for me : Setting a boolean to true as soon as the Future is called, and not calling the Future if the boolean is true :

class _SplashScreenPageState extends State<SplashScreenPage> {

  bool credentialsCalled = false ;

  Future<Widget> _retrieveCredentials() async {
    if (!credentialsCalled) {
      await Requests().getCredentials();
      credentialsCalled = true;
    }
    return SearchPage();
  }

  @override
  Widget build(BuildContext context) {

    return SplashScreen(
      navigateAfterFuture: _retrieveCredentials(),
      // [...]
    );
  }

}

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

6 participants