Получатель 'uid' был вызван на нуль - PullRequest
0 голосов
/ 02 апреля 2020

Ребята, у меня есть эта страница входа с адресом электронной почты и паролем, и когда пользователь успешно вошел в систему, он выводит его на экран чата. На экране чата мне нужно получить доступ к uid пользователей, чтобы проверить, кто отправляет сообщение, но я получаю «Получатель uid» был вызван по нулевому значению ». Я использую шаблон blo c для входа с валидаторами. Как я могу исправить эту ситуацию?

class LoginScreen extends StatefulWidget {
   FirebaseUser user;

   @override
   _LoginScreenState createState() => _LoginScreenState();
    }

   class _LoginScreenState extends State<LoginScreen> {

       final _loginBloc = LoginBloc();

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

       _loginBloc.outState.listen((state) async {
        switch (state) {
          case LoginState.SUCCESS:
            Navigator.of(context).pushReplacement(
               MaterialPageRoute(builder: (context) => ComercialUserScreen()));

            break;
            case LoginState.FAIL:
              showDialog(
           context: context,
           builder: (context) => AlertDialog(
                title: Text('Erro'),
                content: Text('Revise seu email e senha'),
              ));
         break;
       case LoginState.LOADING:
       case LoginState.IDLE:
      }
   });
  }

   @override
     Widget build(BuildContext context) {
      return Scaffold(
         body: StreamBuilder<LoginState>(
      stream: _loginBloc.outState,
      initialData: LoginState.LOADING,
      // ignore: missing_return
      builder: (context, snapshot) {
        print(snapshot.data);
        switch (snapshot.data) {
          case LoginState.LOADING:
            return Center(
              child: CircularProgressIndicator(),
            );
          case LoginState.FAIL:
          case LoginState.SUCCESS:
          case LoginState.IDLE:
            return Column(
              crossAxisAlignment: CrossAxisAlignment.stretch,
              children: <Widget>[
                InputField(
                  icon: Icons.person_outline,
                  hint: 'Usuário',
                  obscure: false,
                  stream: _loginBloc.outEmail,
                  onChanged: _loginBloc.changeEmail,
                ),
                InputField(
                  icon: Icons.lock_outline,
                  hint: 'Senha',
                  obscure: true,
                  stream: _loginBloc.outEmail,
                  onChanged: _loginBloc.changePassword,
                ),
                SizedBox(
                  height: 32,
                ),
                StreamBuilder<bool>(
                    stream: _loginBloc.outSubmitValid,
                    builder: (context, snapshot) {
                      return RaisedButton(
                        child: Text("Entrar"),
                        onPressed:
                            snapshot.hasData ? _loginBloc.submit : null,
                      );
                    })
              ],
            );
        }
      }),
    );
   }
  }

 class LoginBloc extends BlocBase with LoginValidators{

    FirebaseUser _currentUser;

    final _emailController = BehaviorSubject<String>();
    final _passwordController = BehaviorSubject<String>();
    final _stateController = BehaviorSubject<LoginState>();

    Stream<String> get outEmail => _emailController.stream.transform(validateEmail);
    Stream<String> get outPassword =>_passwordController.stream.transform(validatePassword);
    Stream<LoginState> get outState => _stateController.stream;

    Stream<bool> get outSubmitValid => Observable.combineLatest2(
    outEmail, outPassword, (a, b) => true);

    Function(String) get changeEmail => _emailController.sink.add;
    Function(String) get changePassword => _passwordController.sink.add;

    StreamSubscription _streamSubscription;

    LoginBloc(){
        _streamSubscription = FirebaseAuth.instance.onAuthStateChanged.listen((user) async {
          if(user != null) {
            if(await verifyAdmins(user)) {
             _stateController.add(LoginState.SUCCESS);

        } else {
           FirebaseAuth.instance.signOut();
          _stateController.add(LoginState.FAIL);
        }

       } else {
         _stateController.add(LoginState.IDLE);
         }
      });
     }

     void submit (){
     final email = _emailController.value;
     final password = _passwordController.value;

      _stateController.add(LoginState.LOADING);

      FirebaseAuth.instance.signInWithEmailAndPassword(
      email: email,
      password: password
       ).catchError((e) {
      _stateController.add(LoginState.FAIL);
    });
  }

   Future<bool> verifyAdmins (FirebaseUser user) async {
    return await Firestore.instance.collection('users').document(user.uid).get().then((doc) 
    {
    if(doc.data != null){
     return true;
     } else {
      return false;
     }
    }).catchError((e) {
   return false;
  });
 }




@override
 void dispose() {
  _emailController.close();
  _passwordController.close();
  _stateController.close();

  _streamSubscription.cancel();
  // TODO: implement dispose
 }
}


 class _AdminChatState extends State<AdminChat> {

    bool _isLoading = false;

    void _sendMessage({String text, File imgFile}) async {

     DocumentSnapshot snapshot;

     FirebaseUser user = await FirebaseAuth.instance.currentUser();

     Map<String, dynamic> data = {
       "uid" : user.uid,
       'name' : user.displayName,
       'photo' : user.photoUrl,
       'time' : Timestamp.now()
      };

      if (imgFile != null){
         StorageUploadTask task = FirebaseStorage.instance.ref().child('users').child(
         DateTime.now().millisecondsSinceEpoch.toString()
       ).putFile(imgFile);

        setState(() {
        _isLoading = true;
         });

         StorageTaskSnapshot taskSnapshot = await task.onComplete;
         String url = await taskSnapshot.ref.getDownloadURL();
         data['imgUrl'] = url;

         setState(() {
          _isLoading = false;
         });
         }


      if(text != null) data["text"] = text;


       Firestore.instance.collection("users").document(snapshot.documentID)
       .collection('messages').add(data);

      }



     @override
      Widget build(BuildContext context) {
       return Scaffold(
         appBar: AppBar(
           title: Text('hello'),

         ),
          body: Column(
           children: <Widget>[
            Expanded(
             child: StreamBuilder<QuerySnapshot>(
               stream: 
       Firestore.instance.collection('users').document(widget.snapshot.documentID)
       .collection('messages').orderBy('time').snapshots(),
              builder: (context, snapshot){
               switch(snapshot.connectionState) {
                  case ConnectionState.none:
                  case ConnectionState.waiting:
                   return Center(
                     child: CircularProgressIndicator(),
                    );
                  default:
                    List<DocumentSnapshot> documents =
                    snapshot.data.documents.reversed.toList();

                return ListView.builder(
                    itemCount: documents.length,
                    reverse: true,
                    itemBuilder: (context, index){
                      // ignore: unrelated_type_equality_checks
                      return ChatMessage(documents[index].data, true);
                    });
            }
          },

          ),
         ),
      _isLoading ? LinearProgressIndicator() : Container(),
      TextComposer(_sendMessage),
    ],
   ),
  );
 }
 }

1 Ответ

0 голосов
/ 02 апреля 2020

Команда await FirebaseAuth.instance.currentUser(); в _AdminChatState не возвращает никаких данных, поэтому при попытке вставить данные на основе пользователя возвращает ноль. Это происходит потому, что вы не можете использовать await, пока состояние не инициализировано. Если это произойдет, весь класс будет ждать, пока пользователь не вернется. Кроме того, вы используете запрос хранилища с тем же логом c. Если вы хотите, чтобы виджет состояния запускал что-то при запуске, вы можете использовать функцию initState(). Если вы хотите отображать индикатор выполнения во время ожидания возврата данных FutureBuilder или StreamBuilder, это отличный выбор.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...