带有底部导航栏的页面之间的数据传递 [英] Passing data between pages with bottom navigation bar in flutter

查看:147
本文介绍了带有底部导航栏的页面之间的数据传递的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

I have an app that routes to a "mainapp" page after logging in. This app contains a bottom navigation bar which displays pages of the corresponding pressed icon. I want to pass data of type Map<String, dynamic> to these pages but I am having trouble. This map is generated from a function that fetches the data from a server, saves it to shared preferences, then loads the shared preferences and returns it as a map (all contained in getData()). I want to pass this map around so I don't have to load shared preferences each time, but will also update this map along with shared preferences when needed( possibly an action on one of the pages).

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)是否可以帮助您,但不确定这是否是正确的方法。我也不确定在这种情况下如何开始实施它们。

I'm getting an error saying Only static members can be accessed in initializers. I was wondering if inherited widgets or other design patterns such as scoped model and BLoC can help but not sure if that's the right way to go. I'm also not sure how I would start implementing them in this case.

推荐答案

您的代码中有两个问题:

There are two problems in your code:


  1. initState()主体中使用异步方法
    参见中了解详情

  1. using an async method in the body of initState() see here for details

在初始化程序中使用实例数据,在小部件上运行async-operation-on-widget-creation / rel = noreferrer>
请参见
此处详细信息

using instance data in an initializer see here for details

接下来的工作是对您的代码进行非常基本的重写,并进行了最少的修改。

What follow is a very basic rewrite of your code, with minimal corrections.

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

The data map is loaded from a mocked backend, updated inside PageOne and printed to console in PageTwo onTap callback.

请注意,我已将实例变量 Data 更改为数据符合有效的Dart指南。

Please note that I've changed instance variable Data to data to be compliant with Effective Dart guidelines.

请注意,要点未正确解决后端同步问题具有共享首选项的服务:最终产品中可能要考虑到这一点。

Note that the gist does not properly addresses the synchronization of the backend service with the shared preferences: this is something that have probably to be accounted in the final product.

我只是评论了使代码正常工作所必需的:$ b如果系统的复杂性以及与外部API的关系开始增长,则$ b值得考虑使用Bloc架构。

I just commented what it is necessary to get your code works: if the complexity of your system and the relations with external API start growing it could be worth considering a Bloc architecture.

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) {
    if (index == 0) {
      return PageOne(data:data);
    }
    if (index == 1) {
      return PageTwo(data:data);
    }
    // A fallback, in this case just PageOne
    return PageOne();
  }

  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,
          ),
        ));
  }
}

这篇关于带有底部导航栏的页面之间的数据传递的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆