【问题标题】:How to get the data in User Model class from firebase flutter如何从firebase颤振中获取用户模型类中的数据
【发布时间】:2021-07-27 04:39:22
【问题描述】:

我正在使用Firebase 创建应用程序。

我的Users.dart 文件:

  class Users{

  final String id;
  final String profileName;
  final String userName;
  final String url;
  final String email;
  final String bio;

  Users({
    this.id,
    this.profileName,
    this.userName,
    this.url,
    this.email,
    this.bio
  });

  factory Users.fromDocument(DocumentSnapshot doc){
    return Users(
        id: doc.data()['id'],
        email: doc.data()['email'],
        userName: doc.data()['userName'],
        url: doc.data()['url'],
        profileName: doc.data()['profileName'],
        bio: doc.data()['bio']
    );
  }
}

现在看Auth.dart文件:

import 'package:cloud_firestore/cloud_firestore.dart';
import  'package:firebase_auth/firebase_auth.dart' as auth;
import 'package:mms/models/User.dart';
import 'package:mms/screens/Homepage.dart';

class Auth{

  final auth.FirebaseAuth _auth = auth.FirebaseAuth.instance;
  final firebaseUser = auth.FirebaseAuth.instance.currentUser;

  Users _userFromFirebaseUser(auth.User user){
    return user != null ? Users(id: user.uid) : null;
  }

  Future login(String email, String password) async {
    try{
      auth.UserCredential result = await _auth.signInWithEmailAndPassword(email: email, password: password);
      auth.User user = result.user;
      return _userFromFirebaseUser(user);
    } catch(e){
      print(e.toString());
      return null;
    }
  }

  //signup and create user on Firebase
  Future register(String name, String email, String password) async {
    try{
      auth.UserCredential result = await _auth.createUserWithEmailAndPassword(email: email, password: password);
      auth.User user = result.user;
      return _userFromFirebaseUser(user);
    } catch(e){
      print(e.toString());
      return null;
    }
  }
  //signing out from the app
  Future signOut() async {
    try{
      return await _auth.signOut();
    } catch(e){
      print(e.toString());
      return null;
    }
  }
}

现在,当用户在我的应用上创建帐户到 Firestore 时,我正在保存数据,如下所示:

saveUserInfoToFirestore() async {
    var firebaseUser = auth.FirebaseAuth.instance.currentUser;
    DocumentSnapshot documentSnapshot =
        await firestoreInstance.collection('users').doc(firebaseUser.uid).get();

    if (!documentSnapshot.exists) {
      //final profileName = await Navigator.push(context, MaterialPageRoute(builder: (context) => SignupPage()));
      firestoreInstance.collection("users").doc(firebaseUser.uid).set({
        "uid": firebaseUser.uid,
        "profileName": _name,
        "email": firebaseUser.email,
        "timestamp": timestamp,
        "bio": ""
      }).then((_) => print('Success'));
      documentSnapshot = await firestoreInstance
          .collection('users')
          .doc(firebaseUser.uid)
          .get();
    }
    currentUser = Users.fromDocument(documentSnapshot); //currentUser is the instance of Users model class
  }
}

现在每当我打电话给users.id 我都会收到错误提示

The method '[]' was called on null.
Receiver: null
Tried calling: []("id")

我已经在我的Search.dart 中按以下方式致电users.id

import 'package:cloud_firestore/cloud_firestore.dart';
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:mms/models/Progress.dart';
import 'package:mms/models/User.dart';
import 'package:mms/screens/ActivityFeed.dart';
import 'package:mms/screens/Homepage.dart';

class SearchPage extends StatefulWidget {

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

class _SearchPageState extends State<SearchPage> {
  TextEditingController searchTextEditingController = TextEditingController();
  Future<QuerySnapshot> futureSearchResults;
  String profileName;

  void initState(){
    super.initState();
    getProfileName();
  }
  clear() {
    searchTextEditingController.clear();
  }
  Future<void> getProfileName() async {
    final firestoreInstance = FirebaseFirestore.instance;
    firestoreInstance
        .collection("users")
        .doc(firebaseUser.uid)
        .get()
        .then((value) {
      setState(() {
        profileName = value.data()["profileName"].toString();
      });
    });
  }
  searchController(String str) {
    Future<QuerySnapshot> allUsers = FirebaseFirestore.instance
        .collection("users")
        .where("profileName", isGreaterThanOrEqualTo: str)
        .get();
    setState(() {
      futureSearchResults = allUsers;
    });
  }

  Container displayNoSearchResultScreen() {
    final Orientation orientation = MediaQuery.of(context).orientation;
    return Container(
      child: Center(
        child: ListView(
          shrinkWrap: true,
          children: <Widget>[
            Icon(
              Icons.group,
              color: Colors.grey,
              size: 200.0,
            ),
            Text(
              'Find Users',
              textAlign: TextAlign.center,
              style: TextStyle(
                  color: Colors.white,
                  fontWeight: FontWeight.w500,
                  fontSize: 50.0),
            )
          ],
        ),
      ),
    );
  }

  displayUsersFoundScreen() {
    return FutureBuilder(
        future: futureSearchResults, builder: (context, dataSnapshot) {
          if(!dataSnapshot.hasData){
            return circularProgress();
          }


          //This part is also not working properly
          List<UserResult> searchUserResult = [];
          dataSnapshot.data.docs.forEach((document){
            Users users = Users.fromDocument(document);
            UserResult userResult = UserResult(users);
            searchUserResult.add(userResult);
          });
          return ListView(children: searchUserResult,);
    });
  }

  AppBar searchPageHeader() {
    return AppBar(
      backgroundColor: Colors.black,
      title: TextFormField(
        style: TextStyle(fontSize: 18.0, color: Colors.white),
        controller: searchTextEditingController,
        decoration: InputDecoration(
            hintText: "Search",
            hintStyle: TextStyle(color: Colors.grey),
            enabledBorder: UnderlineInputBorder(
                borderSide: BorderSide(color: Colors.grey)),
            focusedBorder: UnderlineInputBorder(
                borderSide: BorderSide(color: Colors.white)),
            filled: true,
            prefixIcon: Icon(
              Icons.person_pin,
              color: Colors.white,
              size: 30.0,
            ),
            suffixIcon: IconButton(
              icon: Icon(
                Icons.clear,
                color: Colors.white,
              ),
              onPressed: clear,
            )),
        onFieldSubmitted: searchController,
      ),
    );
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      backgroundColor: Colors.black,
      appBar: searchPageHeader(),
      body: futureSearchResults == null
          ? displayNoSearchResultScreen()
          : displayUsersFoundScreen(),
    );
  }
}

class UserResult extends StatelessWidget {

  final Users users;
  UserResult(this.users);

  @override
  Widget build(BuildContext context) {
    return Padding(
        padding: EdgeInsets.all(3.0),
      child: Container(
        color: Colors.white54,
        child: Column(
          children: <Widget>[
            GestureDetector(
              onTap: () => showProfile(context, profileId: users.id),//Here I have called but not working
              child: ListTile(
                //leading: CircleAvatar(backgroundColor: Colors.blue, backgroundImage: CachedNetworkImageProvider(users.url),),
                title: Text(users.profileName, style: TextStyle(
                  color: Colors.black, fontSize: 16.0, fontWeight: FontWeight.bold,
                ),),
             
              ),
            )
          ],
        ),
      ),
    );
  }
}

我找不到的错误是什么?如果有人知道解决方案,请告诉我?

【问题讨论】:

  • 你能说明你在哪里以及如何打电话给users.id吗?我在您的代码示例中看不到任何地方。
  • @TarikHuber 我已经编辑了我的问题,现在您可以看到我所做的搜索查询。这里在 UserResult 我有用户模型类的构造函数。

标签: firebase flutter dart google-cloud-firestore firebase-authentication


【解决方案1】:

我发现的一个错误是您在searchController 中缺少await

 Future<void> searchController(String str) async {
    QuerySnapshot allUsers = await FirebaseFirestore.instance
        .collection("users")
        .where("profileName", isGreaterThanOrEqualTo: str)
        .get();
    setState(() {
      futureSearchResults = allUsers;
    });
  }

这里也是await 问题:

saveUserInfoToFirestore() async {
    var firebaseUser = auth.FirebaseAuth.instance.currentUser;
    DocumentSnapshot documentSnapshot =
        await firestoreInstance.collection('users').doc(firebaseUser.uid).get();

    if (!documentSnapshot.exists) {
      //final profileName = await Navigator.push(context, MaterialPageRoute(builder: (context) => SignupPage()));
      await firestoreInstance.collection("users").doc(firebaseUser.uid).set({
        "id": firebaseUser.uid,
        "profileName": _name,
        "email": firebaseUser.email,
        "timestamp": timestamp,
        "bio": ""
      })
      documentSnapshot = await firestoreInstance
          .collection('users')
          .doc(firebaseUser.uid)
          .get();
    }
    currentUser = Users.fromDocument(documentSnapshot); //currentUser is the instance of Users model class
  }
}

使用方法:


  displayUsersFoundScreen() {

          if(!futureSearchResults.hasData){
            return circularProgress();
          }


          //This part is also not working properly
          List<UserResult> searchUserResult = [];
          futureSearchResults.data.docs.forEach((document){
            Users users = Users.fromDocument(document);
            UserResult userResult = UserResult(users);
            searchUserResult.add(userResult);
          });
          return ListView(children: searchUserResult,);
    
  }

【讨论】:

  • 当我按照您的代码放置等待时,我收到错误,因为“无法将“QuerySnapshot”类型的值分配给“Future”类型的变量
  • 我已经更新了分析器。请您再试一次。
  • 我又试了一次。现在它需要 await 关键字,但错误出现在 setState() 中。因为allUsers 是QuerySnapshot 的类型,但“futureSearchResults”是Future&lt;QuerySnapshot&gt; 的类型。我无法更改futureSearchResults 的类型,因为如果您看到displayUsersFoundScreen,则进一步将其用作FutureBuilder
  • 我已经更新了答案。它显示了如何更改displayUsersFoundScreen。因为我们等待结果你不需要使用FutureBuilder
  • 我已经使用了您的解决方案,但我没有在 if 检查中获得方法 hasData,而是我使用了 isEmpty。但最后错误与我在id was called on null 的问题中所写的相同。
猜你喜欢
  • 2022-10-06
  • 2021-02-16
  • 1970-01-01
  • 2019-01-01
  • 2019-01-03
  • 1970-01-01
  • 2019-04-20
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多