1

I am trying to store a value and based on the value I want to navigate to LandinPage or HomePage. However when my app loads I am not able to get the SharedPreferences value. Currently, the value is set on click of a button in Landing page, and when I close/minimize the app. I don't even get to see the print messages from main.dart and can't fetch values. What am I doing wrong?

Here is my code:

import 'package:credit/src/pages/landing.dart';
import 'package:flutter/material.dart';
import 'package:credit/src/pages/credit/home.dart';
import 'package:shared_preferences/shared_preferences.dart';

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

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

  _LoadingPageState createState() => _LoadingPageState();
}

class _LoadingPageState extends State<MyApp> {
  @override
  void initState() {
    super.initState();
    getUserStatus().then((userStatus) {
      if (userStatus == null) {
        Navigator.of(context)
            .push(MaterialPageRoute<Null>(builder: (BuildContext context) {
          return LandingPage();
        }));
      } else {
        Navigator.of(context)
            .push(MaterialPageRoute<Null>(builder: (BuildContext context) {
          return HomePage();
        }));
      }
    });
  }

  @override
  Widget build(BuildContext context) {
    return Container(
        child: Center(
      child: CircularProgressIndicator(),
    ));
  }
}

Future<String> getUserStatus() async {
  SharedPreferences prefs = await SharedPreferences.getInstance();
  String userStatus = prefs.getString('userstatus');
  print("==On Load Check ==");
  print(userStatus);
  return userStatus;
}

5 Answers 5

4

You may need to use a "loading page" that is first loaded before any of your two pages:

import 'package:flutter/material.dart';
import 'package:shared_preferences/shared_preferences.dart';

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

class MyApp extends StatelessWidget {
  // This widget is the root of your application.
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'An App',
      home: LoadingPage(),
      routes: {
        '/landing': (context) => LandingPage(),
        '/home': (context) => HomePage(),
      }
    );
  }
}


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

  _LoadingPageState createState() => _LoadingPageState();
}

class _LoadingPageState extends State<LoadingPage> {
  @override
  void initState() {
    super.initState();
     loadPage();
  }

  loadPage() {
     getUserStatus().then((userStatus) {
      if (userStatus == null) {
        Navigator.of(context).pushNamed('/landing');
      } else {
        Navigator.of(context).pushNamed('/home');
      }
    });
  }

  @override
  Widget build(BuildContext context) {
    return Container(
        child: Center(
      child: CircularProgressIndicator(),
    ));
  }
}

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

  _HomePageState createState() => _HomePageState();
}

class _HomePageState extends State<HomePage> {
  @override
  Widget build(BuildContext context) {
    return Container(
       child: Text('Home Page'),
    );
  }
}

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

  _LandingPageState createState() => _LandingPageState();
}


class _LandingPageState extends State<LandingPage> {

  @override
  void initState() {
    super.initState();
    setUserStatus('done');
  }

  @override
  Widget build(BuildContext context) {
    return Container(
       child: Text('Landing'),
    );
  }
}

Future<String> getUserStatus() async {
  SharedPreferences prefs = await SharedPreferences.getInstance();
  String userStatus = prefs.getString('userStatus');
  print("==On Load Check ==");
  print(userStatus);
  return userStatus;
}

Future<bool> setUserStatus(String userStatus) async{
  SharedPreferences prefs = await SharedPreferences.getInstance();
  prefs.setString('userStatus', userStatus);
  return true;
}
Sign up to request clarification or add additional context in comments.

3 Comments

I tired using the same approach, however, I got an error which says " Navigator operation requested with a context that does not include a Navigator. E/flutter ( 8838): The context used to push or pop routes from the Navigator must be that of a widget that is a descendant of a Navigator widget" I belive it is not getting the correct context, I have updated original code. Any idea wwhy is that?
I have edited the code to make it a full running example. Just copy and paste and edit to your liking. I usually use named routes but you can edit it and see if it works with route builder.
@WillieNandi When I press the back button from the "Landing page" one circle is spinning, how to directly exit from the app.
2

you must add

  @override
  void initState() {
  getUserStatus();
  super.initState();
  }

  var name;
  void getUserStatus() async {
     SharedPreferences prefs= await SharedPreferences.getInstance();

     setState(() {
       userStatus = prefs.getString("userStatus");
   });
  }

2 Comments

Your answer could be improved with additional supporting information. Please edit to add further details, such as citations or documentation, so that others can confirm that your answer is correct. You can find more information on how to write good answers in the help center.
Arif has used the setState() method to solve this problem (this worked in my case)
1

You've declared a method main of MyApp but it never gets called. The main that starts the app is the one with runApp in it. You could move the prefs.getString() into the real main (having made it async) and then pass the value into the MyApp widget as a parameter.

Comments

1

I feel like Willie's answer may be just as good, but here's another approach.

Overall, my approach would be to load the main home page automatically, and then in the initstate of the home page, check to see if this is the user's first visit to the app. If so, pop the landing page on top immediately. I've used this approach successfully without the user having a poor experience.

Below is the default app but with your SharedPreferences code moved to the appropriate spot.

import 'package:flutter/material.dart';
import 'package:shared_preferences/shared_preferences.dart';

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

class MyApp extends StatelessWidget {
  // This widget is the root of your application.
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter Demo',
      theme: ThemeData(
        primarySwatch: Colors.blue,
      ),
      home: MyHomePage(title: 'Flutter Demo Home Page'),
    );
  }
}

class MyHomePage extends StatefulWidget {
  MyHomePage({Key key, this.title}) : super(key: key);

  final String title;

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

class _MyHomePageState extends State<MyHomePage> {
  int _counter = 0;

  void _incrementCounter() {
    setState(() {
      _counter++;
    });
  }

  var userStatus;

  //If user status is null, then show landing page.
  Future<void> checkUserStatus() async {
    SharedPreferences prefs = await SharedPreferences.getInstance();
    userStatus = prefs.getString('userstatus');
    print("==On Load Check ==");
    print(userStatus);

    if (userStatus == null) {
      Navigator.push(context, MaterialPageRoute(builder: (context) => LandingPage()));
    }

  }


  @override
  void initState() {
    super.initState();

    //Call check for landing page in init state of your home page widget
    checkUserStatus();
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        // Here we take the value from the MyHomePage object that was created by
        // the App.build method, and use it to set our appbar title.
        title: Text(widget.title),
      ),
      body: Center(

        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: <Widget>[
            Text(
              'You have pushed the button this many times:',
            ),
            Text(
              '$_counter',
              style: Theme.of(context).textTheme.display1,
            ),
          ],
        ),
      ),
      floatingActionButton: FloatingActionButton(
        onPressed: _incrementCounter,
        tooltip: 'Increment',
        child: Icon(Icons.add),
      ), // This trailing comma makes auto-formatting nicer for build methods.
    );
  }
}


class LandingPage extends StatefulWidget {
  @override
  _LandingPageState createState() => _LandingPageState();
}

class _LandingPageState extends State<LandingPage> {
  @override
  Widget build(BuildContext context) {
    //Build landing page here.
    return Container();
  }
}

1 Comment

Thanks, Eric, I did think through of the same approach, but held back thinking will it cause a flicker momentarily ? or a flash of homepage before getting re-directed to landing page. I will give this a try though.
1

I know this question is old and already been answered but for my situation, Richard Heap's answer was more suitable so I would like to add a code snippet for others.

I only cite part of it, so please modify it if you are going to use it for your app. After the Landing/Welcome page is viewed by user, update the preference by setBool and it won't show up after that.

void main() async {
  // do whatever
  SharedPreferences prefs = await SharedPreferences.getInstance();
  bool hideWelcome = prefs.getBool('hideWelcome') ?? false;
  // start your app
  runApp(MyApp(hideWelcome));
}

class MyApp extends StatelessWidget {
  final hideWelcome;

  MyApp(this.hideWelcome);

  @override
  Widget build(BuildContext context) {
      return MaterialApp(
          // other setting like theme, title
          initialRoute: hideWelcome ? '/' : '/welcome',
          routes: {
              '/': (context) => MyHomePage(),
              '/welcome': (context) => WelcomePage(),
              // other pages
          }
      );
}

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.