Flutter:SharedPreferences在应用启动时未获取值

时间:2019-07-27 19:16:07

标签: flutter

我试图存储一个值,并根据该值导航到LandinPage或HomePage。但是,当我的应用加载时,我无法获取SharedPreferences值。当前,该值是在“着陆页”上单击按钮时以及在我关闭/最小化该应用程序时设置的。我什至看不到来自main.dart的打印消息,并且无法获取值。我究竟做错了什么?

这是我的代码:

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

4 个答案:

答案 0 :(得分:1)

您可能需要使用首先在两个页面中的任何一个之前加载的“加载页面”:

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

答案 1 :(得分:1)

我知道这个问题很老,已经有人回答了,但对于我的情况,Richard Heap 的回答更合适,所以我想为其他人添加一个代码片段。

我只引用了其中的一部分,因此如果您打算将其用于您的应用程序,请对其进行修改。登陆/欢迎页面完成后,只需更新首选项值,之后就不会显示了。

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

答案 2 :(得分:0)

您已经声明了main中的方法MyApp,但是从未调用过它。启动应用程序的main是其中带有runApp的应用程序。您可以将prefs.getString()移到真实的main(使其变为异步),然后将该值作为参数传递到MyApp小部件中。

答案 3 :(得分:0)

我觉得Willie的回答可能同样好,但这是另一种方法。

总体而言,我的方法是自动加载主主页,然后在主页的初始状态下检查这是否是用户首次访问该应用程序。如果是这样,请立即在顶部弹出登录页面。我已经成功地使用了这种方法,而不会给用户带来糟糕的体验。

以下是默认应用,但您的SharedPreferences代码已移至适当位置。

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