为什么共享首选项中的数据延迟了?

时间:2019-08-14 17:08:45

标签: flutter sharedpreferences

我有一个屏幕可以显示共享首选项中的数据。我已经成功保存并从共享首选项中获取数据。然后我在这样的一个屏幕中有一个流程:

  1. 如果用户单击该屏幕,它将检查共享首选项中的数据。
  2. 如果数据不为空/不为空,则将显示数据登录信息,例如用户个人资料等。
  3. 如果数据为空/空,将显示按钮登录。

我得到了该流程的逻辑,但是问题是,在屏幕上显示数据(数字2)之前,它先显示按钮登录几毫秒,然后再显示数据。为什么会发生?它没有来自API / Internet的数据,并且我没有使用FutureBuilder,而是使用了共享首选项。如何杀死这个延迟?下面是我的完整代码:

class MorePage extends StatefulWidget {
  @override
  _MorePageState createState() => _MorePageState();
}

class _MorePageState extends State<MorePage> {

  bool isLoading = false;
  SessionManager _sessionManager = SessionManager();
  int status;

  @override
  void initState() {
    super.initState();
    _sessionManager.getStatusLogin().then((value) { //i use this for get status code login success
      setState(() {
        status = value;
      });
    });
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      backgroundColor: color_grey_bg,
      body: SafeArea(
        child: getMorePage(),
      ),
    );
  }

  Widget getMorePage() {
    return ListView(
      physics: ClampingScrollPhysics(),
      children: <Widget>[
        Container(
          padding: EdgeInsets.only(
            left: MediaQuery.of(context).size.width / 20,
          ),
          height: MediaQuery.of(context).size.width / 4,
          width: MediaQuery.of(context).size.width,
          color: color_white,
          child: setProfile(),
        ),
      ],
    );
  }

  Widget setProfile() {
    if (status == 200) { // i use this logic to show widget with status login, but it's have delayed like show data from API. How to kill it? Because I using SharedPreferences, not hit the API
      return profileUser();
    } else {
      return notSignIn();
    }
  }

  Widget profileUser() {
    return Row(
      children: <Widget>[
        Column(
          mainAxisSize: MainAxisSize.max,
          mainAxisAlignment: MainAxisAlignment.center,
          crossAxisAlignment: CrossAxisAlignment.start,
          children: <Widget>[
            Text(
              name,
              style: TextStyle(
                color: color_grey_text,
                fontSize: MediaQuery.of(context).size.width / 26,
                fontWeight: FontWeight.bold,
              ),
            ),
            Text(
              email,
              style: TextStyle(
                color: color_grey_text,
                fontSize: MediaQuery.of(context).size.width / 30,
                fontWeight: FontWeight.normal,
              ),
            ),
            Text(
              role,
              style: TextStyle(
                color: color_grey_text,
                fontSize: MediaQuery.of(context).size.width / 35,
                fontWeight: FontWeight.normal,
              ),
            ),
          ],
        ),
        Spacer(),
        IconButton(
          icon: Icon(
            Icons.arrow_forward_ios,
            size: MediaQuery.of(context).size.height / 40,
          ),
          onPressed: () {
            Navigator.push(context, MaterialPageRoute(builder: (context) => DetailUserPage()));
          },
        ),
      ],
    );
  }

  Widget notSignIn() {
    return Padding(
      padding:
          EdgeInsets.only(left: 50.0, right: 50.0, top: 30.0, bottom: 30.0),
      child: RaisedGradientButton(
        child: Text(
          'Login',
          style: TextStyle(
              color: color_white,
              fontSize: MediaQuery.of(context).size.width / 25),
        ),
        gradient: LinearGradient(
          colors: <Color>[color_blue, color_green],
        ),
        onPressed: () {
          Navigator.push(
              context, MaterialPageRoute(builder: (context) => LoginPage()));
        },
      ),
    );
  }
}

这是用于创建shared_preferences功能的SessionManager类:

class SessionManager {

  .....

  getStatusLogin() async {
    SharedPreferences preferences = await SharedPreferences.getInstance();
    int status = preferences.getInt("status");
    return status;
  }

  ....

}

3 个答案:

答案 0 :(得分:0)

getprofile函数实际上是未来,您使用了async await关键字。 确实,从sharedpref检索数据并不需要花费时间,但是获取sharedpref的实例是原因的根源。因此,您必须选择解决此解决方案的方法。

1- 在主函数中获取共享首选项的实例。您可以获取共享首选项的实例,并将其作为参数传递给整个应用程序。

示例

void main ()async{
    final instance = await sharedPreference.getInstance();
    runApp(MyApp(instance));}

现在在您的MorePage小部件中

    class _MorePageState extends State<MorePage> {
  LoginStatus _loginStatus = LoginStatus.notSignIn;
  SessionManager _sessionManager = SessionManager();
  String name, email, role;
  //no need for the async keyword
  getProfile()  { //this func just for show the data

    name = widget.preferences.getString("fullname");
    email = widget.preferences.getString("email");
    role = widget.preferences.getString("role");
  }

  @override
  void initState() {
    super.initState();
    getProfile();
    _sessionManager.getLoginStatus().then((value) {  //this code for get the status of login
      setState(() {
        _loginStatus = value;
      });
    });
  }

现在getProfile函数不是异步的,这意味着没有毫秒可以使这种奇怪的行为在开始时出现。

2- 设置另一个枚举值“忙” (更简单的解决方案)。只需简单地保留代码即可,但是添加一个新的枚举值,该值正忙于向用户提示该应用正在检查他是否已登录,您只需在设置配置文件功能中给他该提示,即可将创建另一个条件if ( _loginStatus == LoginStatus.busy ) return Text('checking user Info')

希望有帮助!

编辑: 您可以使用该软件包get_it来创建会话管理器类的单例实例,并且可以在任何地方访问它。

GetIt locator = GetIt();

void setUpLocator() {
  locator.registerLazySingleton(() => SessionManager());
}

void main() async {
  setUpLocator();
  await locator.get<SessionManager>().getStatusLogin();
  runApp(MyApp());
}

class MorePage extends StatefulWidget {
  @override
  _MorePageState createState() => _MorePageState();
}

class _MorePageState extends State<MorePage> {
  bool isLoading = false;
  final _sessionManager = locator.get<SessionManager>();
  int status;

  @override
  void initState() {
    super.initState();
      //make  property of statuesif you don't have property of the statues 
        //in the session manager class

    status = _sessionManager.statues;
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      backgroundColor: color_grey_bg,
      body: SafeArea(
        child: getMorePage(),
      ),
    );
  }

  Widget getMorePage() {
    return ListView(
      physics: ClampingScrollPhysics(),
      children: <Widget>[
        Container(
          padding: EdgeInsets.only(
            left: MediaQuery.of(context).size.width / 20,
          ),
          height: MediaQuery.of(context).size.width / 4,
          width: MediaQuery.of(context).size.width,
          color: color_white,
          child: setProfile(),
        ),
      ],
    );
  }

  Widget setProfile() {
    if (status == 200) {
      // i use this logic to show widget with status login, but it's have delayed like show data from API. How to kill it? Because I using SharedPreferences, not hit the API
      return profileUser();
    } else {
      return notSignIn();
    }
  }

  Widget profileUser() {
    return Row(
      children: <Widget>[
        Column(
          mainAxisSize: MainAxisSize.max,
          mainAxisAlignment: MainAxisAlignment.center,
          crossAxisAlignment: CrossAxisAlignment.start,
          children: <Widget>[
            Text(
              name,
              style: TextStyle(
                color: color_grey_text,
                fontSize: MediaQuery.of(context).size.width / 26,
                fontWeight: FontWeight.bold,
              ),
            ),
            Text(
              email,
              style: TextStyle(
                color: color_grey_text,
                fontSize: MediaQuery.of(context).size.width / 30,
                fontWeight: FontWeight.normal,
              ),
            ),
            Text(
              role,
              style: TextStyle(
                color: color_grey_text,
                fontSize: MediaQuery.of(context).size.width / 35,
                fontWeight: FontWeight.normal,
              ),
            ),
          ],
        ),
        Spacer(),
        IconButton(
          icon: Icon(
            Icons.arrow_forward_ios,
            size: MediaQuery.of(context).size.height / 40,
          ),
          onPressed: () {
            Navigator.push(context,
                MaterialPageRoute(builder: (context) => DetailUserPage()));
          },
        ),
      ],
    );
  }

  Widget notSignIn() {
    return Padding(
      padding:
          EdgeInsets.only(left: 50.0, right: 50.0, top: 30.0, bottom: 30.0),
      child: RaisedGradientButton(
        child: Text(
          'Login',
          style: TextStyle(
              color: color_white,
              fontSize: MediaQuery.of(context).size.width / 25),
        ),
        gradient: LinearGradient(
          colors: <Color>[color_blue, color_green],
        ),
        onPressed: () {
          Navigator.push(
              context, MaterialPageRoute(builder: (context) => LoginPage()));
        },
      ),
    );
  }
}

答案 1 :(得分:0)

我认为显示Circle Progress一旦从共享的pref获取值,然后显示主容器。

请检查以下代码:-

feh

答案 2 :(得分:0)

我认为您应该创建一个类,然后使用引用-:

export default

现在您可以引用它(“ ShareP.preferences”)并获取您的SharedPreference值