【问题标题】:Problem with local variable - Global variable flutter dart局部变量的问题 - 全局变量颤振飞镖
【发布时间】:2019-07-28 14:17:31
【问题描述】:

当使用BottomAppBar 时,我想通过不同的页面传递动态数据。我目前在页面/小部件之间切换,我的存储方式如下:

  @override
  void initState() {
    super.initState();
    final _pageOptions = [
    SwipeScreen(currentUserId: currentUserId),
    Requests(currentUserId: currentUserId),
    Messages(currentUserId: currentUserId),
    Settings(),
  ];}

然后我在我的Scaffold 中使用_pageOptions

  body: _pageOptions[_selectedPage],
  bottomNavigationBar: BottomNavigationBar(
    currentIndex: _selectedPage,
    onTap: (int index) {
      setState(() {
        _selectedPage = index;
      });
    },

正如您可能已经猜到的那样,我不能在Scaffold 中使用_pageOptions 作为我的主体,因为它在包裹在initState() 中时是一个局部变量。我必须使用这个 initState,因为没有它,我只能在我的初始化程序中传递静态成员。

我不知道如何解决这个问题,因为删除一个只会给我一个不同的错误。我一直在寻找使变量全局化的方法,例如在不同的文件中使用 _pageOptions,但它仍然是本地的,因此在我的 Scaffold 中使用时没有定义。

我希望我的问题很清楚。

提前致谢。

【问题讨论】:

    标签: dart flutter


    【解决方案1】:

    这并不是刻薄,只是诚实,所以请不要生气,但是从事情的声音开始,您需要从一些关于颤振如何工作以及如何在颤振中开发事物的基本教程重新开始.我建议从头到尾在 Flutter 网站上完成几个 tutorialscodelabs (直到你看到最终代码),然后看看你所做的与他们不同。甚至可能是getting started with Dart documentation...

    对您的问题最简单的答案是简单地将 _pageOptions 设置为您的类的成员变量,因为这样您就可以从任何需要的地方访问它。但是由于您遇到了只能“在我的初始化程序中传递静态成员”的问题,这可能意味着您没有在正确的位置初始化事物。

    使用 Flutter 开发时要记住以下几点:

    1. 您不应该在除构建函数之外的任何地方创建小部件(除非您创建一个从构建函数调用的辅助函数 - 但如果您这样做,可能是因为小部件变大了,您应该将其拆分出来到它自己的有状态或无状态小部件中)
    2. 除非您知道自己在做什么,否则不应继承小部件。大多数时候你只会继承StatelessWidget和StatefulWidget,其他的都是通过封装完成的(即在构建函数中使用它们)
    3. 通过更改使用数组构建的内容来简单地切换页面并不是一种好方法 - 导航时不会获得动画之类的东西,您可能会比需要的东西更快地构建东西,并且会失去像页面的状态,除非您注意自己的操作方式。
    4. 在 Flutter 中构建小部件的成本很低,您通常应该为每个页面构建大部分小部件。在某些情况下并非如此,但对于基本应用程序,为每个屏幕构建导航栏(但将构建它的实际逻辑拆分为无状态或有状态小部件!)

    #3 的解决方案是使用flutter's navigation 并在MaterialApp(routes: ...)MaterialApp(onGenerateRoute: ...) 中定义您的页面。因此,您将为 SwipeScreen、请求、消息和设置设置路由。您可以使用 Navigator.pushNavigator.pushNamedNavigator.pop 在它们之间移动。

    为了避免到处复制和粘贴底部导航栏,请将其拆分为自己的小部件,即MyBottomNavigationBar extends StatelessWidget。然后在每个页面中都有一个 Scaffold(body: ..., bottomNavigationBar: MyBottomNavigationBar())。如果您的脚手架变得非常复杂,您甚至可以将其移动到自己的小部件中。

    哦,我刚刚阅读了您问题的重要部分:I want to pass dynamic data through different pages。使用我所描述的导航器会稍微改变这一点,因为您不想将其传递到构建的每一层。

    有多种方法可以解决这个问题 - 最基本的是使用 InheritedWidget,但由于它需要大量样板文件才能使其工作,我建议使用 ScopedModel。这样,您只需创建一个从 Model 继承的类(即 UserModel),然后在选择/登录用户时更改模型中的信息并通知侦听器(即 userId)。像这样:

    class UserModel extends Model {
      String _userId;
    
      String get userId => _userId;
    
      void setUser(String userId) {
        _userId = userId;
        notifyListeners();
      }
    
      static CounterModel of(BuildContext context, {bool rebuildOnChange = false}) =>
        ScopedModel.of<CounterModel>(context, rebuildOnChange = rebuildOnChange);
    }
    

    您需要将它放在小部件树中的某个较高位置(可能在 MaterialApp 上方或 MaterialApp(builder: ...) 中)。然后,您可以为该模型添加名称、配置文件、颜色等,并在您的应用中的任何需要的地方使用所有这些。

    【讨论】:

    • 感谢警钟
    【解决方案2】:

    你想在同一个班级使用_pageOptions 吗?如果是这样应该可以解决您的问题。

      var _pageOptions;
      // declare a variable inside your class/outside of your initState to reach it from anywhere inside in your class
      @override
      void initState() {
        super.initState();
        _pageOptions = [
        SwipeScreen(currentUserId: currentUserId),
        Requests(currentUserId: currentUserId),
        Messages(currentUserId: currentUserId),
        Settings(),
        ];
      }
    

    【讨论】:

      猜你喜欢
      • 2022-11-16
      • 1970-01-01
      • 1970-01-01
      • 2019-07-24
      • 2017-11-08
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多