flutter 如何使用FutureBuilder处理异步身份验证和导航?

b1uwtaje  于 2023-05-19  发布在  Flutter
关注(0)|答案(1)|浏览(189)

尝试在我的演示应用程序上设置身份验证检查器。目前使用shared_preferences包存储从demo API获取的jwt token。
我已经组合了一个函数,它返回Future bool来验证我们是否存储了一个令牌,以及该令牌是否未过期:

Future<bool> isUserAuthenticated() async {
    if (tokenIsStored) {
        if (tokenIsNotExpired) {
            return true;
        }
    }
    return false;
}

因此,在MyHomePage状态下,我正在考虑使用FutureBuilder来处理验证

class _MyHomePageState extends State<MyHomePage> {

  Future<bool> isUserAuthenticated = Future.delayed(const Duration(seconds: 1), () => API().isUserAuthenticated());

  @override
  Widget build(BuildContext context) {
    return FutureBuilder(
      future: isUserAuthenticated,
      builder: (context, snapshot) {
        if (snapshot.hasData) {
          if (snapshot.data as bool) {
            return Text("Hello");
          } else {
            return const LoginPage();
          }
        }
        return CircularProgressIndicator();
      },
    );
  }
}

然后通过LoginPage请求jwt token并导航回MyHomePage

ElevatedButton(
  onPressed: () {
    setState(() => waitingForAPI = true);
    String username = usernameController.text;
    String password = passwordController.text;
    API().login(username, password).then((credsWereValid) {
      if (credsWereValid) {
        Navigator.pushNamed(context, '/home');
      }
    });
  }
)

这会创建一个“总是转发”的流,如:

MyHomePage -> LoginPage -> MyHomePage

我不知道为什么,但这看起来不像是一个好的流动。我认为正确的流程应该是从LoginPage返回Navigator.pop调用:

MyHomePage -> LoginPage
MyHomePage <- LoginPage

我相信要做到这一点,我们需要重新修改我的主页如下:

class _MyHomePageState extends State<MyHomePage> {

  Future<bool> isUserAuthenticated = Future.delayed(const Duration(seconds: 1), () => API().isUserAuthenticated());

  @override
  Widget build(BuildContext context) {
    return FutureBuilder(
      future: isUserAuthenticated,
      builder: (context, snapshot) {
        if (snapshot.hasData) {
          if (snapshot.data as bool) {
            return Text("Hello");
          } else {
            // return const LoginPage();
            Navigator.pushNamed(context, '/login');
          }
        }
        return CircularProgressIndicator();
      },
    );
  }
}

LoginPage逻辑如下:

ElevatedButton(
  onPressed: () {
    setState(() => waitingForAPI = true);
    String username = usernameController.text;
    String password = passwordController.text;
    API().login(username, password).then((credsWereValid) {
      if (credsWereValid) {
        Navigator.pop(context);
      }
    });
  }
)

我的问题是我应该坚持哪一种设计模式?还是应该追求另一种设计模式?

fdx2calv

fdx2calv1#

FutureBuilderNavigator是一次性使用的auth方法。
有一个简单的方法可以让这个过程顺利地来回进行:在身份验证页面中生成一个Stream的身份验证状态数据,然后使用一个Provider在转换页面中侦听该数据。
有关详细说明,您可以参考此video

相关问题