局部变量出现问题-全局变量扑镖

时间:2019-03-06 19:52:52

标签: dart flutter

使用BottomAppBar时,我想通过不同的页面传递动态数据。我目前在页面/小部件之间进行切换,如下所示:

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

然后我在_pageOptions中使用Scaffold

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

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

我不知道该如何解决,因为删除一个错误只会给我一个不同的错误。我一直在寻找使变量成为全局变量的方法,例如将_pageOptions放在另一个文件中,但是它仍然是局部变量,因此在我的Scaffold中使用时未定义。

我希望我的问题很清楚。

谢谢。

2 个答案:

答案 0 :(得分:1)

这并不是要刻薄,只是说实话,请不要冒犯,但是从事物的声音上,您需要重新开始一些有关颤振如何工作以及如何在颤振中发展事物的基础教程。 。我建议从头到尾遍历Flutter网站上的几个tutorialscodelabs(直到您查看最终代码之前),然后看看您所做的工作有所不同从他们。甚至getting started with Dart documentation ...

最简单的答案是让_pageOptions成为类的成员变量,因为它使您可以从任何需要的地方访问它。但是,由于您遇到的问题是只能“通过初始化程序中的静态成员”,因此,这可能意味着您未在正确的位置初始化事物。

在用颤动进行开发时,需要牢记以下几点:

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

#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: ...)中)。然后,您可以为该模型添加名称,配置文件,颜色等,并在应用程序中的任何位置使用所有这些名称。

答案 1 :(得分:0)

您是否要在同一课程中使用_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(),
    ];
  }