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

2023-12-22

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

class MainApp extends StatefulWidget {
  @override
  _MainAppState createState() => _MainAppState();
}

class _MainAppState extends State<MainApp> {


  Map<String, dynamic> Data;


  StartFunc() async {
   Data = await getData();
   setState(() {}); 
 }


  @override
  void initState() {
    StartFunc();
    super.initState();
  }

  var _pages = [
    PageOne(Data:Data),
    PageTwo(),
    PageThree(),
   PageFour(),
   PageFive(),
  ];

  int _currentIndex = 0;

  onTabTapped(int index) {
    setState(() {
      _currentIndex = index;
    });
  }

  @override
  Widget build(BuildContext context) {
    return _currentIndex == 2
        ? PageTwo()
        : Scaffold(
      body: _pages[_currentIndex],
      bottomNavigationBar: BottomNavigationBar(
        type: BottomNavigationBarType.fixed,
        items: [
          BottomNavigationBarItem(
              icon: Icon(Icons.library_books), title: Text('')),
          BottomNavigationBarItem(
              icon: Icon(Icons.notifications), title: Text('')),
          BottomNavigationBarItem(
              icon: Icon(Icons.add_circle_outline), title: Text('')),
          BottomNavigationBarItem(
              icon: Icon(Icons.mail), title: Text('')),
          BottomNavigationBarItem(
              icon: Icon(Icons.person), title: Text('')),
        ],
        onTap: onTabTapped,
        currentIndex: _currentIndex,
      ),
    );
  }
}

我收到一条错误消息只能在初始化程序中访问静态成员。我想知道继承的小部件或其他设计模式(例如范围模型和 BLoC)是否可以提供帮助,但不确定这是否是正确的方法。我也不确定在这种情况下我将如何开始实施它们。


您的代码中有两个问题:

  1. 在主体中使用异步方法initState() see here https://flutter.institute/run-async-operation-on-widget-creation/欲了解详情

  2. 在初始化程序中使用实例数据 看here https://stackoverflow.com/questions/50145150/error-only-static-members-can-be-accessed-in-initializers-what-does-this-mean欲了解详情

接下来是对代码的非常基本的重写,并进行了最少的更正。

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

请注意,我已经更改了实例变量Data to data遵守有效飞镖 https://www.dartlang.org/guides/language/effective-dart/style#do-name-other-identifiers-using-lowercamelcase指导方针。

请注意,要点没有正确解决后端服务与共享首选项的同步:这可能需要在最终产品中考虑。

我只是评论了让您的代码正常工作所需的条件: 如果您的系统的复杂性以及与外部 API 的关系开始增长,那么可能值得考虑 Bloc 架构。

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,
          ),
        ));
  }
}
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

在flutter中使用底部导航栏在页面之间传递数据 的相关文章

随机推荐