Dart 在颤振中使用底部导航栏在页面之间传递数据

Dart 在颤振中使用底部导航栏在页面之间传递数据,dart,flutter,Dart,Flutter,我有一个应用程序,在登录后路由到“mainapp”页面。此应用程序包含一个底部导航栏,显示相应按下图标的页面。我想将Map类型的数据传递到这些页面,但遇到了问题。此映射是由一个函数生成的,该函数从服务器获取数据,将其保存到共享首选项,然后加载共享首选项并将其作为映射返回(全部包含在getData()中)。我想传递此地图,这样我就不必每次都加载共享首选项,但也会在需要时随共享首选项一起更新此地图(可能是其中一个页面上的操作) class MainApp扩展StatefulWidget{ @凌驾 _

我有一个应用程序,在登录后路由到“mainapp”页面。此应用程序包含一个底部导航栏,显示相应按下图标的页面。我想将
Map
类型的数据传递到这些页面,但遇到了问题。此映射是由一个函数生成的,该函数从服务器获取数据,将其保存到共享首选项,然后加载共享首选项并将其作为映射返回(全部包含在
getData()
中)。我想传递此地图,这样我就不必每次都加载共享首选项,但也会在需要时随共享首选项一起更新此地图(可能是其中一个页面上的操作)

class MainApp扩展StatefulWidget{
@凌驾
_MainAppState createState()=>\u MainAppState();
}
类_MainAppState扩展状态{
地图数据;
StartFunc()异步{
数据=等待获取数据();
setState((){});
}
@凌驾
void initState(){
StartFunc();
super.initState();
}
变量_页=[
第一页(数据:数据),
第二页(),
第三页(),
第四页(),
第五页(),
];
int _currentIndex=0;
onTabTapped(int索引){
设置状态(){
_currentIndex=索引;
});
}
@凌驾
小部件构建(构建上下文){
返回_currentIndex==2
?第二页()
:脚手架(
正文:_页[_当前索引],
底部导航栏:底部导航栏(
类型:BottomNavigationBarType.fixed,
项目:[
底部导航气压计(
图标:图标(Icons.library_books),标题:Text(“”)),
底部导航气压计(
图标:图标(图标.通知),标题:文本(“”)),
底部导航气压计(
图标:图标(图标。添加圆圈\轮廓),标题:文本(“”)),
底部导航气压计(
图标:图标(Icons.mail),标题:文本(“”)),
底部导航气压计(
图标:图标(Icons.person),标题:文本(“”)),
],
onTap:onTabTapped,
currentIndex:_currentIndex,
),
);
}
}

我得到一个错误,说在初始化器中只能访问静态成员。我想知道继承的小部件或其他设计模式(如作用域模型和BLoC)是否有帮助,但不确定这是否正确。我也不确定在这种情况下如何开始实施它们

代码中有两个问题:

  • initState()的主体中使用异步方法
    有关详细信息,请参阅

  • 在初始值设定项中使用实例数据 有关详细信息,请参阅

  • 下面是对代码的一个非常基本的重写,只需很少的修改

    数据映射从模拟后端加载,在
    PageOne
    内部更新,并在
    PageTwo
    onTap回调中打印到控制台

    请注意,我已将实例变量
    Data
    更改为
    Data
    ,以符合指导原则

    请注意,gist没有正确地解决后端服务与共享首选项的同步问题:这可能是最终产品中必须考虑的问题

    我刚刚评论了使代码正常工作所必需的内容: 如果您的系统的复杂性以及与外部API的关系开始增长,那么值得考虑采用集团架构

    import 'package:flutter/material.dart';
    
    void main() => runApp(new MainApp());
    
    // Mock up of an async backend service
    Future<Map<String, dynamic>> getData() async {
      return Future.delayed(Duration(seconds: 1), () => {'prop1': 'value1'});
    }
    
    class PageOne extends StatelessWidget {
      final Map<String, dynamic> data;
    
      PageOne({Key key, this.data}) : super(key: key);
    
      @override
      Widget build(BuildContext context) {
        return Center(
          child: RaisedButton(
            child: const Text('update preferences'),
            onPressed: () {
              data['prop2'] = 'value2';
            },
          ),
        );
      }
    }
    
    class PageTwo extends StatelessWidget {
    
      final Map<String, dynamic> data;
    
      PageTwo({Key key, this.data}) : super(key: key);
    
      @override
      Widget build(BuildContext context) {
        return Center(
          child: RaisedButton(
            child: const Text('Got It!'),
            onPressed: () {
              print("data is now: [$data]");
            },
          ),
        );
      }
    }
    
    class MainApp extends StatefulWidget {
      @override
      _MainAppState createState() => _MainAppState();
    }
    
    class _MainAppState extends State<MainApp> {
      //Map<String, dynamic> Data;
      Map<String, dynamic> data;
    
      /*
      StartFunc() async {
        Data = await getData();
        setState(() {});
      }
      */
    
      @override
      void initState() {
        //StartFunc();
        super.initState();
        getData().then((values) {
          setState(() {
            data = values;
          });
        });
      }
    
      /*
      PageOne(data:data) is an invalid value for an initializer:
       there is no way to access this at this point.
        Initializers are executed before the constructor,
        but this is only allowed to be accessed after the call
        to the super constructor.
    
      */
      /*
      var _pages = [
        PageOne(data:data),
        PageTwo(),
      ];
      */
    
     Widget getPage(int index) {
        switch (index){
            case 0:
                return PageOne(data:data);
                break;
            case 1:
                return PageTwo(data:data);
                break;
            default:
                return PageOne();
            break;
        }
      }
    
      int _currentIndex = 0;
    
      onTabTapped(int index) {
        setState(() {
          _currentIndex = index;
        });
      }
    
      @override
      Widget build(BuildContext context) {
        /*
        return _currentIndex == 2
            ? PageTwo()
            : Scaffold(
    
        I use a MaterialApp because of material widgets (RaisedButton)
        It is not mandatory, but it is mainstream in flutter
    
         */
        return MaterialApp(
            title: 'My App',
            home: Scaffold(
              appBar: AppBar(title: Text("My App Bar")),
              body: getPage(_currentIndex),
              bottomNavigationBar: BottomNavigationBar(
                type: BottomNavigationBarType.fixed,
                items: [
                  BottomNavigationBarItem(
                      icon: Icon(Icons.first_page), title: Text('')),
                  BottomNavigationBarItem(
                      icon: Icon(Icons.last_page), title: Text('')),
                ],
                onTap: onTabTapped,
                currentIndex: _currentIndex,
              ),
            ));
      }
    }
    
    导入“包装:颤振/材料.省道”;
    void main()=>runApp(新的MainApp());
    //异步后端服务的模型
    Future getData()异步{
    返回Future.delayed(持续时间(秒:1),()=>{'prop1':'value1'});
    }
    类PageOne扩展了无状态小部件{
    最终地图数据;
    PageOne({Key-Key,this.data}):超级(Key:Key);
    @凌驾
    小部件构建(构建上下文){
    返回中心(
    孩子:升起按钮(
    子项:常量文本(“更新首选项”),
    已按下:(){
    数据['prop2']='value2';
    },
    ),
    );
    }
    }
    类PageTwo扩展了无状态小部件{
    最终地图数据;
    PageTwo({Key-Key,this.data}):super(Key:Key);
    @凌驾
    小部件构建(构建上下文){
    返回中心(
    孩子:升起按钮(
    child:const Text('Got!'),
    已按下:(){
    打印(“数据现在为:[$data]”;
    },
    ),
    );
    }
    }
    类MainApp扩展StatefulWidget{
    @凌驾
    _MainAppState createState()=>\u MainAppState();
    }
    类_MainAppState扩展状态{
    //地图数据;
    地图数据;
    /*
    StartFunc()异步{
    数据=等待获取数据();
    setState((){});
    }
    */
    @凌驾
    void initState(){
    //StartFunc();
    super.initState();
    getData()。然后((值){
    设置状态(){
    数据=数值;
    });
    });
    }
    /*
    PageOne(数据:data)对于初始值设定项是无效值:
    在这一点上没有办法访问这个。
    初始化器在构造函数之前执行,
    但这只允许在通话后访问
    到超级构造函数。
    */
    /*
    变量_页=[
    第一页(数据:数据),
    第二页(),
    ];
    */
    小部件getPage(int索引){
    开关(索引){
    案例0:
    返回第一页(数据:数据);
    打破
    案例1:
    返回第二页(数据:数据);
    打破
    违约:
    返回PageOne();
    打破
    }
    }
    int _currentIndex=0;
    onTabTapped(int索引){
    设置状态(){
    _currentIndex=索引;
    });
    }
    @凌驾
    小部件构建(构建上下文){
    /*
    返回_currentIndex==2
    ?第二页()
    :脚手架(
    我使用MaterialApp是因为material小部件(RaisedButton)
    这不是强制性的,但它是颤振的主流
    */
    返回材料PP(
    标题:“我的应用程序”,
    家:脚手架(
    appBar:appBar(标题:文本(“我的应用程序栏”),
    正文:getPage(_currentIndex),
    底部导航栏:底部导航栏(
    类型:BottomNavigationBarType.fixed,
    信息技术
    
    import 'package:flutter/material.dart';
    
    void main() => runApp(new MainApp());
    
    // Mock up of an async backend service
    Future<Map<String, dynamic>> getData() async {
      return Future.delayed(Duration(seconds: 1), () => {'prop1': 'value1'});
    }
    
    class PageOne extends StatelessWidget {
      final Map<String, dynamic> data;
    
      PageOne({Key key, this.data}) : super(key: key);
    
      @override
      Widget build(BuildContext context) {
        return Center(
          child: RaisedButton(
            child: const Text('update preferences'),
            onPressed: () {
              data['prop2'] = 'value2';
            },
          ),
        );
      }
    }
    
    class PageTwo extends StatelessWidget {
    
      final Map<String, dynamic> data;
    
      PageTwo({Key key, this.data}) : super(key: key);
    
      @override
      Widget build(BuildContext context) {
        return Center(
          child: RaisedButton(
            child: const Text('Got It!'),
            onPressed: () {
              print("data is now: [$data]");
            },
          ),
        );
      }
    }
    
    class MainApp extends StatefulWidget {
      @override
      _MainAppState createState() => _MainAppState();
    }
    
    class _MainAppState extends State<MainApp> {
      //Map<String, dynamic> Data;
      Map<String, dynamic> data;
    
      /*
      StartFunc() async {
        Data = await getData();
        setState(() {});
      }
      */
    
      @override
      void initState() {
        //StartFunc();
        super.initState();
        getData().then((values) {
          setState(() {
            data = values;
          });
        });
      }
    
      /*
      PageOne(data:data) is an invalid value for an initializer:
       there is no way to access this at this point.
        Initializers are executed before the constructor,
        but this is only allowed to be accessed after the call
        to the super constructor.
    
      */
      /*
      var _pages = [
        PageOne(data:data),
        PageTwo(),
      ];
      */
    
     Widget getPage(int index) {
        switch (index){
            case 0:
                return PageOne(data:data);
                break;
            case 1:
                return PageTwo(data:data);
                break;
            default:
                return PageOne();
            break;
        }
      }
    
      int _currentIndex = 0;
    
      onTabTapped(int index) {
        setState(() {
          _currentIndex = index;
        });
      }
    
      @override
      Widget build(BuildContext context) {
        /*
        return _currentIndex == 2
            ? PageTwo()
            : Scaffold(
    
        I use a MaterialApp because of material widgets (RaisedButton)
        It is not mandatory, but it is mainstream in flutter
    
         */
        return MaterialApp(
            title: 'My App',
            home: Scaffold(
              appBar: AppBar(title: Text("My App Bar")),
              body: getPage(_currentIndex),
              bottomNavigationBar: BottomNavigationBar(
                type: BottomNavigationBarType.fixed,
                items: [
                  BottomNavigationBarItem(
                      icon: Icon(Icons.first_page), title: Text('')),
                  BottomNavigationBarItem(
                      icon: Icon(Icons.last_page), title: Text('')),
                ],
                onTap: onTabTapped,
                currentIndex: _currentIndex,
              ),
            ));
      }
    }