使用 Futurebuilder 有条件地渲染小部件

Posted

技术标签:

【中文标题】使用 Futurebuilder 有条件地渲染小部件【英文标题】:Using Futurebuilder to render widgets conditionally 【发布时间】:2020-01-25 00:49:21 【问题描述】:

我是 Flutter 和 Dart 的新手。所以我正在尝试在 Flutter 中构建一个简单的身份验证系统。当用户打开应用程序时,我想在他们登录时向他们显示LoginScreen(他们以前没有登录的地方)或HomeScreen

loadWidget,它返回一个Future 将确定是否存在持久数据,从而获取用户信息并显示主屏幕。 child 属性不允许我为其分配 Future,我不确定,但我想我必须为此使用 FutureBuilder 小部件?

第一次尝试

  Future<Widget> loadWidget() async
    SharedPreferences prefs = await SharedPreferences.getInstance();

    // already logged in
    String phone = prefs.getString('phoneNumber');
    if (phone != null)      
      helper.user = await checkUser(phone); // fetch user info
      return HomeScreen();
    
    // Not logged in
    else 
      return Login();
    
  

对于构建功能,这不起作用

Widget build(BuildContext context) 
    return MaterialApp(
      home: Scaffold(
        body: loadWidget(), // This does not allow me to assign a future
    )
);
  

第二次尝试:使用 FutureBuilder 我在这里阅读了有关 Futurebuilder how to assign future<> to widget in flutter? 的信息,它看起来像是要走的路,所以我将构建方法修改为

Widget build(BuildContext context) 
    return MaterialApp(
      home: Scaffold(
        body: FutureBuilder(
          future: loadWidget(),
          builder: (BuildContext context, AsyncSnapshot<Widget> widget)
            return widget;
          ,
        ),
      ),
    );
  

但这给了我以下错误:

返回类型“AsyncSnapshot”不是定义的“Widget” 通过匿名关闭。

我怎样才能做到这一点?谢谢!

【问题讨论】:

【参考方案1】:

我会将未来移到 FutureBuilder 中,然后将逻辑放入其中

  Widget build(BuildContext context) 
    return MaterialApp(
      home: Scaffold(
        body: FutureBuilder(
            future: loadWidget(),
            builder: (BuildContext context, AsyncSnapshot<Widget> sharedPreference) 
              String phone = sharedPreference.getString('phoneNumber');
              if (phone != null) 
                return HomeScreen();
              
              // Not logged in
              else 
                return Login();
              
            ),
      ),
    );
  

【讨论】:

【参考方案2】:

您做得对,但问题在于 FutureBuilder 的返回对象,请参阅此代码中的 cmets:

// *NOTE: build return Widget: Widget build...
Widget build(BuildContext context) 
    return MaterialApp(
      home: Scaffold(
        body: FutureBuilder(
          future: loadWidget(),
          builder: (BuildContext context, AsyncSnapshot<Widget> widget)
            // But 'widget' here is NOT a widget, it is an AsyncSnapshot object,
            // return widget; // **is wrong**
            // instead:
            return widget.data;

            // and better to make it like this:
            //if (!widget.hasData) 
            //  return Center(
            //    child: CircularProgressIndicator(),
            //  );
            //
            //return widget.data;
          ,
        ),
      ),
    );
  

那是为了修复错误。关于更简洁代码的额外建议,通过使其仅返回状态(Auth 或 Not)来保持身份验证层(loadWidget)的清洁,然后在 FutureBuilder 中使用 widget.data 捕获状态,然后根据 Auth 状态进行路由从FutureBuilder 内部。

【讨论】:

这行得通。另外,谢谢你的建议,会记住的:)

以上是关于使用 Futurebuilder 有条件地渲染小部件的主要内容,如果未能解决你的问题,请参考以下文章

Flutter futureBuilder 正在渲染未知的褪色卡片

如何使用 clsx 有条件地渲染 css?

使用单选按钮有条件地渲染组件

如何通过 map 函数有条件地使用 React 和 Firebase 渲染元素?

有条件地渲染 tr,使用 ui:repeat 构建表

我怎样才能更好地有条件地渲染我的组件?