为什么共享首选项中的数据延迟了? [英] Why get data from shared preferences have a delayed?

查看:104
本文介绍了为什么共享首选项中的数据延迟了?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

I have one screen to display data from shared preferences. I already success save and get data from shared preferences. Then I have a flow in one screen like this:

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

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

I get the logic for that flow, but the problem is, before data showing in the screen (number 2), it shows button login first for a few milliseconds then show the data. Why did it happen? It's not got data from API / internet and I'm not using FutureBuilder, I just using Shared Preferences. How to kill this delayed? Below is my full code:

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类:

And this is class SessionManager for create function of shared_preferences:

class SessionManager {

  .....

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

  ....

}

推荐答案

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

the getprofile function is actually is a future , you used the async await keywords . it's true that retrieving the data from the sharedpref doesn't take time ,but getting the instance of the sharedpref is the root of the cause . so you have to options to solve this solution .

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

1-getting the instance of the shared pref in the main function. you can get the instance of the shared pref and pass it as argument to the whole application.

示例:

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

现在在您的MorePage小部件中

now in your MorePage widget

    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函数不是异步的,这意味着没有毫秒可以使这种奇怪的行为在开始时出现.

now the getProfile function is not async which means there's no milliseconds that makes that weird behavior at the beginning .

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

2-Make another enum value 'busy' (simpler solution) . simply you can leave you code as it's but add a new enum value which is busy to give hint to the user that the app is checking if he has logined before or not ,you simply will give him that hint in the set profile function , you'll create another condition if ( _loginStatus == LoginStatus.busy ) return Text('checking user Info').

希望有帮助!

您可以使用此程序包 get_it 来创建会话管理器类的单例实例,并且可以在任何地方访问它.

Edit : You this package get_it to make a singleton instance of the session manager class and you can access it anywhere .

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

这篇关于为什么共享首选项中的数据延迟了?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆