简体   繁体   English

异步显示来自 Firebase 的数据 - Flutter

[英]Display data from Firebase in async - Flutter

I want to create a profil page where I just display informations from the user, but I have trouble to reach the data.我想创建一个个人资料页面,我只显示来自用户的信息,但我无法访问数据。 When I want to use my variable user it display 'Instance of Future<Map<String, dynamic>>'当我想使用我的可变用户时,它会显示“Instance of Future<Map<String, dynamic>>”

If I put the 'Widget build' in async I have an error message who told me: ProfileScreen.build' ('Future Function(BuildContext)') isn't a valid override of 'StatelessWidget.build' ('Widget Function(BuildContext)').如果我将“Widget build”置于异步状态,我会收到一条错误消息,告诉我:ProfileScreen.build' ('Future Function(BuildContext)') isn't a valid override of 'StatelessWidget.build' ('Widget Function(BuildContext) )')。

class ProfileScreen extends StatelessWidget {
  ProfileScreen({super.key});

  @override
  Widget build(BuildContext context) {
    final user = displayUser();
    return Scaffold(
        appBar: AppBar(
          title: Text('Profile'),
        ),
        body: Align(
          alignment: Alignment.topLeft,
          child: Column(
              mainAxisAlignment: MainAxisAlignment.start,
              crossAxisAlignment: CrossAxisAlignment.start,
              children: [
                Align(
                  alignment: Alignment.topLeft,
                  child: Column(children: [
                    Text('Prénom :${user}\nNom :\nEmail :',
                        textWidthBasis: TextWidthBasis.longestLine),
                  ]),
                )
              ]),
        ),
        persistentFooterButtons: [
          SignOutButton(),
          BottomNavBar(),
        ]);
  }

  // Get user informations
  Future<Map<String, dynamic>> displayUser() async {
    final User? currentUser = FirebaseAuth.instance.currentUser;
    late final userUid = currentUser?.uid;
    late final ref = FirebaseDatabase.instance.ref();
    final resSnapshot = await ref.child('/utilisateur/' + userUid!).get();
    final Map<String, dynamic> user = {};

    if (resSnapshot.exists) {
      user['id'] = userUid;
      for (var value in resSnapshot.children) {
        String key = value.key as String;
        var val = value.value;
        user[key] = val;
      }
    } else {
      print('No data available.');
    }
    print(user); // This print display exactly the informations I want.
    return user;
  }
}


Thanks for your help.谢谢你的帮助。

Your displayUser is async function and you can't call it inside build method, you need to use FutureBuilder like this:您的displayUserasync的 function 并且您不能在build方法中调用它,您需要像这样使用FutureBuilder

@override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('Profile'),
      ),
      body: FutureBuilder<Map<String, dynamic>>(
        future: displayUser(),
        builder: (context, snapshot) {
          switch (snapshot.connectionState) {
            case ConnectionState.waiting:
              return Text('Loading....');
            default:
              if (snapshot.hasError) {
                return Text('Error: ${snapshot.error}');
              } else {
                Map<String, dynamic> user = snapshot.data ?? {};

                return Align(
                  alignment: Alignment.topLeft,
                  child: Column(
                    mainAxisAlignment: MainAxisAlignment.start,
                    crossAxisAlignment: CrossAxisAlignment.start,
                    children: [
                      Align(
                        alignment: Alignment.topLeft,
                        child: Column(
                          children: [
                            Text(
                              'Prénom :${user}\nNom :\nEmail :',
                              textWidthBasis: TextWidthBasis.longestLine,
                            ),
                          ],
                        ),
                      )
                    ],
                  ),
                );
              }
          }
        },
      ),
      persistentFooterButtons: [
        SignOutButton(),
        BottomNavBar(),
      ],
    );
  }

You can customize loading and error state to what you want.您可以根据需要自定义加载和错误 state。

change StatelessWidget to StatefulWidget because userInteract on profileScreen, UserInteraction changes will show on firebase.StatelessWidget更改为StatefulWidget ,因为userInteract在 profileScreen 上, UserInteraction更改将显示在 firebase 上。

class ProfileScreen extends StatefulWidget{
  ProfileScreen({super.key});

You can load the user in the initstate and then set user using setstate您可以在initstate中加载user ,然后使用setstate设置用户

class ProfileScreen extends StatefulWidget {
  const ProfileScreen({super.key});

  @override
  State<ProfileScreen> createState() => _ProfileScreenState();
}

class _ProfileScreenState extends State<ProfileScreen> {
  Map<String, dynamic>? user;

  @override
  void initState() {
   final User? currentUser = FirebaseAuth.instance.currentUser;
    late final userUid = currentUser?.uid;
    late final ref = FirebaseDatabase.instance.ref();
    final resSnapshot = await ref.child('/utilisateur/' + userUid!).get();
    Map<String, dynamic> temp = {};

    if (resSnapshot.exists) {
      temp['id'] = userUid;
      for (var value in resSnapshot.children) {
        String key = value.key as String;
        var val = value.value;
        temp[key] = val;
      }
    } else {
      print('No data available.');
    }
    print(temp);
    setState((){
    user =temp 
});
    super.initState();
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: Center(
          child:
              user != {} ? Text(user.toString()!) : const CircularProgressIndicator()),
    );
  }
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM