用于聊天应用程序的颤振中的 FutureBuilder

问题描述

我正在使用 Firebase 身份验证创建群聊应用。我的应用程序的流程是让用户注册登录。一旦用户注册登录,他/她就会被带到聊天屏幕,在那里他们可以发送消息。登录流程工作正常。但是在创建新用户时,我无法在聊天屏幕上检索用户数据。这是我的代码示例。

这就是我在屏幕之间切换的方式。

Scaffold(
    body: StreamBuilder(
        builder: (context,snapshot) {
          if (snapshot.hasData &&
              snapshot.connectionState == ConnectionState.active) {
            return ChatScreen();
          } else {
            return AuthScreen();
          }
        },stream: FirebaseAuth.instance.authStateChanges()));

这是用户注册登录代码

class _AuthScreenState extends State<AuthScreen> {
final _auth = FirebaseAuth.instance;
var _isLoading = false;

void _submitAuthForm(
String email,String password,String username,bool isLogin,File f,BuildContext ctx,) async {
UserCredential authResult;

try {
  final collection = FirebaseFirestore.instance.collection('users');
  var imageUrl = '';
  setState(() {
    _isLoading = true;
  });
  if (isLogin) {
    authResult = await _auth.signInWithEmailAndPassword(
      email: email,password: password,);
  } else {
    authResult = await _auth.createuserWithEmailAndPassword(
      email: email,);
    final ref = FirebaseStorage.instance
        .ref()
        .child('user_image')
        .child(authResult.user.uid);

    // await ref
    //     .putFile(f)
    //     .whenComplete(() async => imageUrl = await ref.getDownloadURL());

    await ref.putFile(f);
    final url = await ref.getDownloadURL();

    collection.doc(authResult.user.uid).set({
      'username': username,'email': email,'password': password,'imageFile': url
    });
  }
} on FirebaseAuthException catch (err) {
  String errorMessage = '';
  if (err.code == 'weak-password') {
    errorMessage = 'The password provided is too weak.';
  } else if (err.code == 'email-already-in-use') {
    errorMessage = 'The account already exists for that email.';
  } else if (err.code == 'user-not-found') {
    errorMessage = 'No user found for that email.';
  } else if (err.code == 'wrong-password') {
    errorMessage = 'Wrong password provided for that user.';
  } 
  
  Scaffold.of(ctx).showSnackBar(
    SnackBar(
      content: Text(errorMessage),backgroundColor: Theme.of(ctx).errorColor,),);
  setState(() {
    _isLoading=false;
  });
} on PlatformException catch (err) {
  var message = 'An error occurred,pelase check your credentials!';

  if (err.message != null) {
    message = err.message;
  }

  Scaffold.of(ctx).showSnackBar(
    SnackBar(
      content: Text(message),);
  setState(() {
    _isLoading = false;
  });
} catch (err) {
  setState(() {
    _isLoading = false;
  });
  if (_isLoading == false) {
    Scaffold.of(context).showSnackBar(SnackBar(
      backgroundColor: Theme.of(context).errorColor,content: Text(err.toString()),));
  }
}

}

方法负责从用户集合中检索用户数据。

Future<User> getUserByUid(String uid) async {
  final doc = await collection.doc(uid).get();
   return User.fromJSON(doc.data());
}

这个负责在聊天屏幕上显示数据。

class ChatScreen extends StatefulWidget {
@override
_ChatScreenState createState() => _ChatScreenState();
}

class _ChatScreenState extends State<ChatScreen> {
var future;
@override
void initState() {
super.initState();
future= FirebaseService()
        .getUserByUid(FirebaseAuth.instance.currentUser.uid);

}
@override
Widget build(BuildContext context) {
return FutureBuilder(
    future: _user,builder: (context,snapshot) {
       if (snapshot.connectionState == ConnectionState.done &&
          snapshot.hasData) {
        
        return Scaffold(
            appBar: AppBar(
              toolbarHeight: 70,leading: Container(
                  margin: EdgeInsets.fromLTRB(10,0),child: InkWell(
                    onTap: () {
                      Navigator.of(context)
                          .pushNamed(SettingsScreen.routeName);
                    },child: CircleAvatar(
                      backgroundImage: snapshot.data.imageUrl != null
                          ? NetworkImage(snapshot.data.imageUrl)
                          : null,)),title: Text(
                snapshot.data.username,style: TextStyle(color: Colors.black),backgroundColor: Colors.white,actions: [
                IconButton(
                    color: Colors.white,icon: RadiantGradientMask(
                        child: FaIcon(FontAwesomeIcons.userFriends)),onpressed: () {
                      Navigator.push(
                          context,MaterialPageRoute(
                              builder: (context) => listofFriends()));
                    }),IconButton(
                  //color: Colors.deepPurple,tooltip: 'logout',icon: RadiantGradientMask(
                      child: FaIcon(FontAwesomeIcons.signOutAlt)),onpressed: () {
                    FirebaseAuth.instance.signOut();
                  },)
              ],elevation: 0.5,centerTitle: true,body: Column(
              children: [
                Expanded(child: Messages()),NewMessage(),],));
      } else {
        
        return Center(child: CircularProgressIndicator());
      }
    });

} }

这段代码永远不会从 if 块中出来,循环进度指示器永远持续下去。任何帮助将不胜感激,提前致谢。

解决方法

首先避免将你的未来命名为未来。

回答你:

final Future<String> _user; // add prefix 'late' if you are already using sound null safety.

Future<String> _getUserByUID(final var uid) async {
    return await FirebaseService().getUserByUid(uid);
}

@override
void initState() {
    super.initState();
    _user = _getUserByUID(FirebaseAuth.instance.currentUser.uid);
}

[...]

return FutureBuilder(
    future: _user,[...]

if (snapshot.connectionState == ConnectionState.done && snapshot.hasData) {
      print('the data is ${snapshot.data}');
      return Scaffold(
          appBar: AppBar(
       [...]
));} else
     return Center(child: CircularProgressIndicator());
}

现在应该可以了,如果解决了请告诉我!

编辑:您必须添加 snapshot.hasData 条件,否则您的代码可能会为空;