如何将从“首页”小部件获取的数据快速传递到其子小部件?

时间:2020-10-24 08:00:31

标签: android flutter google-cloud-firestore storage flutter-dependencies

我正在为社区开发一款具有登录,注册,会议和聊天功能的应用程序。成功登录后,路线将转到具有五个底部导航的主页。我正在此应用中使用Firebase进行身份验证和Firestore。

我想在Home组件启动时获取一次数据,并将数据传递给其他五个底部导航栏组件。 现在,每当在导航组件之间切换时,我都会获取数据。这会增加Firestore的读取次数。

我尝试使用构造函数变量通过组件传递数据。但这是行不通的。它显示了无法将数据传递到底部导航组件的错误。这是我的代码。

Home.dart

class Home extends StatefulWidget {
  @override
  _HomeState createState() => _HomeState();
  User currentUser;
  String userId;
  Home({this.currentUser, this.userId});
}

class _HomeState extends State<Home> {
  CurrentUser userInfo;
  DocumentSnapshot doc;
  int _selectedIndex = 0;
  List<String> upcoming_seven_days;
  FirestoreService _firestoreService = FirestoreService();
  static const TextStyle optionStyle =
      TextStyle(fontSize: 30, fontWeight: FontWeight.bold);
  static List<Widget> _widgetOptions = <Widget>[
    Dashboard(),
    MeetingList(),
    EventList(),
    Chat(),
    Profile(),
  ];

  static const List<Widget> _appBarText = <Widget>[
    Text(
      'Dashboard',
      style: TextStyle(
        fontWeight: FontWeight.w300,
        fontSize: 26,
      ),
    ),
    Text(
      'Meetings',
      style: TextStyle(
        fontWeight: FontWeight.w300,
        fontSize: 26,
      ),
    ),
    Text(
      'Events',
      style: TextStyle(fontWeight: FontWeight.w300, fontSize: 26),
    ),
    Text(
      'Chat',
      style: TextStyle(fontWeight: FontWeight.w300, fontSize: 26),
    ),
    Text(
      'Profile',
      style: TextStyle(fontWeight: FontWeight.w300, fontSize: 26),
    ),
  ];

  @override
  void initState() {
    // TODO: implement initState
    super.initState();
    //setCurrentUserID(widget.currentUser.uid);

    //setCurrentUserData(doc.data());
  }

  void _onItemTapped(int index) {
    setState(() {
      _selectedIndex = index;
    });
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: _appBarText.elementAt(_selectedIndex)),
      body: Container(
        padding: EdgeInsets.symmetric(horizontal: 10),
        width: double.maxFinite,
        child: _widgetOptions.elementAt(_selectedIndex),
      ),
      bottomNavigationBar: BottomNavigationBar(
        items: const <BottomNavigationBarItem>[
          BottomNavigationBarItem(
              icon: Icon(Icons.dashboard),
              title: Text('Dashboard'),
              backgroundColor: Colors.black),
          BottomNavigationBarItem(
              icon: Icon(Icons.people),
              title: Text('Meetings'),
              backgroundColor: Colors.black),
          BottomNavigationBarItem(
              icon: Icon(Icons.calendar_view_day),
              title: Text('Events'),
              backgroundColor: Colors.black),
          BottomNavigationBarItem(
              icon: Icon(Icons.chat),
              title: Text('Chat'),
              backgroundColor: Colors.black),
          BottomNavigationBarItem(
              icon: Icon(Icons.person),
              title: Text('Profile'),
              backgroundColor: Colors.black),
        ],
        currentIndex: _selectedIndex,
        selectedItemColor: Colors.lightBlue[200],
        onTap: _onItemTapped,
        elevation: 8.0,
        backgroundColor: Colors.black,
      ),
    );
  }
}

每当用户切换到会议列表组件时,我都将从Firestore中获取数据。我不想那样做。相反,我想将各自的数据从Home传递到其他组件。而且应该是快照,以便可以监听更改。

MeetingList.dart

class MeetingList extends StatelessWidget {
  var userInfo;
  FirebaseAuth firebaseAuth = FirebaseAuth.instance;
  Future getuserinfo() async {
    // final uid = firebaseAuth.currentUser.uid;
    // userinfo = await firestoreService.getCurrentUserInfo(uid);
    // userinfo = userinfo.data().length;
    // //print(userinfo);
    // return uid;
    final uid = firebaseAuth.currentUser.uid;
    DocumentSnapshot user = await FirebaseFirestore.instance
        .collection('userProfiles')
        .doc(uid)
        .get();
    userInfo = user.data();
    return userInfo;
  }

  @override
  Widget build(BuildContext context) {
    CollectionReference meetings =
        FirebaseFirestore.instance.collection('meetings');
    return FutureBuilder(
      future: getuserinfo(),
      builder: (context, AsyncSnapshot snapshot) {
        if (snapshot.connectionState == ConnectionState.waiting) {
          return LoadingIndicator();
        } else {
          return StreamBuilder<QuerySnapshot>(
            stream: meetings.snapshots(),
            builder:
                (BuildContext context, AsyncSnapshot<QuerySnapshot> snapshot) {
              if (snapshot.hasError) {
                return Text('Something went wrong');
              }

              if (snapshot.connectionState == ConnectionState.waiting) {
                return LoadingIndicator();
              }

              return new ListView(
                children: snapshot.data.docs.map((DocumentSnapshot document) {
                  String meetingRole = document.data()['role'];
                  var userRole = userInfo['role'];
                  print(userRole);
                  if (meetingRole == 'all' || meetingRole == userRole) {
                    return Meeting_Card(
                      meeting: document.data(),
                    );
                  } else {
                    return Container();
                  }
                }).toList(),
              );
            },
          );
        }
      },
    );
  }
}

您的帮助将对社区大有帮助。

1 个答案:

答案 0 :(得分:2)

您可以为此使用Provider软件包,它是InheritedWidget周围的包装。

InheritedWidget用于有效地向下传播信息 树,而不必将它们通过各种构造函数 在小部件树下。

您可以找到有关InheritedWidget here的更多信息。

Provider包是用InheritedWidget包裹起来的 更易于使用和可重复使用。

文档here中有关Provider的更多信息

使用Provider实施解决方案: 创建一个名为ChangeNotifier的{​​{1}}类,以保存要在所有子小部件之间公用的数据:

UserProvider

现在将class UserProvider extends ChangeNotifier { User userInfo; Future getuserinfo() async { // final uid = firebaseAuth.currentUser.uid; // userinfo = await firestoreService.getCurrentUserInfo(uid); // userinfo = userinfo.data().length; // //print(userinfo); // return uid; final uid = firebaseAuth.currentUser.uid; DocumentSnapshot user = await FirebaseFirestore.instance .collection('userProfiles') .doc(uid) .get(); userInfo = user.data(); return userInfo; } } 小部件包装在Home小部件中:

ChangeNotifierProvider

现在,您可以使用以下方法从同一个窗口小部件树中的任意位置访问class HomeScreen extends StatelessWidget { @override Widget build(BuildContext context) { return ChangeNotifierProvider<UserProvider>( lazy: false, create: (context) => UserProvider(), child: Home(), ); } } 类的内容(任何选项卡)

UserProvider

您还可以查看提供程序包中的/// Get an instance of the UserProvider in the ancestors of the current widget tree like this. UserProvider userProvider = Provider.of<UserProvider>(context); /// Call any method inside the UserProvider class like this userProvider.getUserInfo(); /// access any data variables inside the UserProvider class like this. User userInfo = userProvider.userInfo; Consumer小部件,它们提供了一种基于Selector类的某些参数来重绘UI的有效方法,从ChangeNotifier类中调用notifyListeners()方法时。