【问题标题】:How to rebuild the whole view in flutter everytime view enters the screen每次视图进入屏幕时如何在颤动中重建整个视图
【发布时间】:2020-04-27 00:36:59
【问题描述】:

我希望我的页面在进入页面时始终点击 API。 例如,我有 2 个屏幕,即 FirstScreen 和 SecondScreen。 在 FirstScreen 中,我正在调用 API 来获取一些数据。因此,如果用户从 FirstScreen 导航到 SecondScreen,然后按返回按钮返回 FirstScreen,它应该再次点击 FirstScreen 中的 API。

我想知道flutter中是否有任何内置函数,我应该在其中调用我的方法,以便它每次进入屏幕时都能工作。我尝试过使用 didUpdateWidget(),但它没有按我想要的方式工作。

initState() 也仅在加载小部件后调用.. 请解释一下

【问题讨论】:

    标签: flutter


    【解决方案1】:

    您可以使用async await。假设您有一个更改路线的按钮。

    onPressed: () async {
      await Navigator.of(context).push(
        MaterialPageRoute(
            builder: (context) => SecondScreen(),
          ),
      );
      ApiCall();
    },
    

    ApiCall 函数只会在用户在第二个屏幕上按下后部时调用。

    【讨论】:

    • 场景就像在 Secondscreen 上一样,我根据用户选择更改数据,并且在 FirstScreen 中调用的 API 中传递该 ID。所以一旦 Secondscreen 弹出它应该在 FirstScreen 中再次触发 API,并使用用户在 SecondScreen 中选择的 id 注意:我正在使用本地存储来存储该 id。
    • 您有多种选择。第一个是用pop发送id。从第二屏到第一屏。在第二个屏幕上: RaisedButton( onPressed: () { Navigator.pop(context, id); }, child: Text('Save'), ) 在第一个屏幕上: onPressed: () async { Final id = await Navigator. of(context).push(MaterialPageRoute(builder: (context) => SecondScreen(), ), ); ApiCall(id); },
    • 第二个是在第一个屏幕上从您的存储中加载 id。在第二个屏幕上: RaisedButton( onPressed: () { LocalStorage.save(id) Navigator.pop(context, id); }, child: Text('Save'), ) 在第一个屏幕上: onPressed: () async { final id = await Navigator.of(context).push( MaterialPageRoute( builder: (context) => SecondScreen(), ), );最终 id = LocalStorage.load() ApiCall(id); },
    • 或者你可以使用一些东西作为全局状态管理。 (供应商,集团..等)。然后在第二个屏幕上进行 api 调用并在第一个屏幕上显示它。
    【解决方案2】:

    我有一个例子可能会有所帮助。但是,它可能无法涵盖在来自不同页面/屏幕或特别恢复应用程序(来自后台 - 来时不要混淆)后显示页面时,您的 FirstScreen 将始终调用特定函数的所有场景从另一个屏幕或弹出)。

    然而,我的示例,当您从特定屏幕返回时,将始终调用一个函数,您可以将其重新实现到其他导航函数,以确保从其他导航返回 FirstScreen 时始终调用特定函数屏幕。

    main.dart

    class MyApp extends StatelessWidget {
      @override
      Widget build(BuildContext context) {
        return MaterialApp(
          theme: ThemeData(
            primarySwatch: Colors.blue,
          ),
          home: HomePage(),
        );
      }
    }
    

    home_page.dart

    class HomePage extends StatefulWidget {
      @override
      _HomePageState createState() => _HomePageState();
    }
    
    class _HomePageState extends State<HomePage> {
      @override
      Widget build(BuildContext context) {
        return Scaffold(
          body: Column(
            mainAxisSize: MainAxisSize.max,
            mainAxisAlignment: MainAxisAlignment.center,
            children: <Widget>[
              Center(
                child: RaisedButton(
                  onPressed: () => Navigator.of(context)
                      .push(MaterialPageRoute(builder: (context) => SecondPage()))
                      .then((value) => _reload(value)),
                  child: Text('Navigate to Next Page'),
                ),
              )
            ],
          ),
        );
      }
    
      Future<void> _reload(var value) async {
        print(
            'Home Page resumed after popping/closing SecondPage with value {$value}. Do something.');
      }
    }
    

    second_page.dart

    class SecondPage extends StatefulWidget {
      @override
      _SecondPageState createState() => _SecondPageState();
    }
    
    class _SecondPageState extends State<SecondPage> {
      @override
      Widget build(BuildContext context) {
        return WillPopScope(
          onWillPop: () async {
            Navigator.pop(context, 'Passed Value');
    
            /// It's important that returned value (boolean) is false,
            /// otherwise, it will pop the navigator stack twice;
            /// since Navigator.pop is already called above ^
            return false;
          },
          child: Scaffold(
            appBar: AppBar(),
            body: Column(
              mainAxisSize: MainAxisSize.max,
              mainAxisAlignment: MainAxisAlignment.center,
              children: <Widget>[
                Center(child: Text('Second Page')),
              ],
            ),
          ),
        );
      }
    }
    

    【讨论】:

      【解决方案3】:

      @Rick 的回答即使对于 Riverpod 状态管理也很有魅力,因为我无法重建第一个屏幕以在第二个屏幕上显示优惠券的“已使用”状态的更改,其中有一个按钮可以使用它。
      所以我在详细信息页面上做了:

       return WillPopScope(
            onWillPop: () async {
              //final dumbo = ref.read(userProvider.notifier).initializeUser();
              Navigator.pop(context);
              return false; //true;
            },
      

      然后在优惠券列表页面,每张优惠券卡上有:

      child: Card(
                                  elevation: 10,
                                  shape: RoundedRectangleBorder(
                                    borderRadius: BorderRadius.circular(24.0),
                                    side: BorderSide(
                                        color: coupons[index].isUsed
                                            ? Colors.grey
                                            : Colors.blue),
                                  ),
                                  child: InkWell(
                                    splashColor: Colors.blue.withAlpha(30),
                                    onTap: () {
                                      //go to Details screen with Coupon instance
                                      //https://api.flutter.dev/flutter/widgets/Navigator/pushNamed.html
                                      Navigator.pushNamed(context, '/details',
                                              arguments: coupons[index].couponId)
                                          .then((_) => _reload());
                                      /*Navigator.of(context).push(
                                        MaterialPageRoute(
                                          builder: (_) => DetailsScreen(
                                            coupon: coupons[index],
                                          ),
                                        ),
                                      );*/
                                    },
      

      我使用_ 的地方,因为没有参数。 那么CouponScreen类中的函数就是:

      void _reload() {
           
          setState(() {});
        }
      

      我相信setState(){} 是触发重建的原因。我为格式道歉,但复制和粘贴深层嵌套的 Flutter 代码非常困难。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2021-10-20
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多