如何在 Flutter 中将两个屏幕之一正确导航给用户?

How to Navigate one of the two screens to users correctly in Flutter?

最近我正在用 Flutter 开发第一个应用程序,我只知道基础知识。 这就是我目前面临的问题。

我必须根据 old/new 用户导航两个屏幕之一,注册或主页,所以我所做的就是这里。

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

class Authenticate extends StatefulWidget {
  @override
  _AuthenticateState createState() => _AuthenticateState();
}

class _AuthenticateState extends State<Authenticate> {
  String _userName = "";

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

  _getUserName() async {
    SharedPreferences pref = await SharedPreferences.getInstance();
    setState(() {
      _userName = pref.getString('userName') ?? "";
    });
  }

  Widget build(BuildContext context) {
    if (_userName == "") {
      print('name : $_userName  , NEW user'); // ERROR - why it's printing on console for old User ?
      return Register();
    } else {
      return HomePage(_userName);
    }
  }
}

所以问题是,即使我通过老用户打开应用程序,它也会打印为新用户编写的调试代码,注册屏幕的屏幕可见性约为 0.3 秒。

那么我应该怎么做才能解决这个问题?

正在打印,因为这行代码:

SharedPreferences pref = await SharedPreferences.getInstance();

是异步的,这意味着它可能会在稍后的某个时间点调用。因为 build 方法首先被调用,然后你的 _getUserName 方法完成,这导致 setState 并再次调用 build 方法。

您可能希望在初始化 sharedPrefernces 之前显示某种加载程序屏幕,然后决定是否显示 RegisterHome 页面。

示例代码:

class _AuthenticateState extends State<Authenticate> {
  String _userName = "";
  bool _isLoading = true;

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

  _getUserName() async {
    SharedPreferences pref = await SharedPreferences.getInstance();
    setState(() {
      _userName = pref.getString('userName') ?? "";
      _isLoading = false;
    });
  }

  Widget build(BuildContext context) {
    if (_isLoading) {
      return Center(child: CupertinoActivityIndicator());
    } else if (_userName == "") {
      print('name : $_userName  , NEW user'); // ERROR - why it's printing on console for old User ?
      return Register();
    } else {
      return HomePage(_userName);
    }
  }
}

试试这个:

class _AuthenticateState extends State<Authenticate> {
  String _userName;

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

  _getUserName() async {
    SharedPreferences pref = await SharedPreferences.getInstance();
    setState(() {
      _userName = pref.getString('userName') ?? '';
    });
  }

  Widget build(BuildContext context) {
    if (_userName == null) {
      return Center(child: CircularProgressIndicator());
    } else if (_userName == '') {
      print('name : $_userName  , NEW user');
      return Register();
    } else {
      return HomePage(_userName);
    }
  }
}

在这种情况下,_userName 最初是 null,并且只会在 _getUserName() return 之后分配一个空字符串或旧用户名。当为 null 时,小部件将构建一个进度指示器。如果你不想这样,只需 return a Container().