为啥 Firebase 实时数据库的数据在控制台中显示为空?

Posted

技术标签:

【中文标题】为啥 Firebase 实时数据库的数据在控制台中显示为空?【英文标题】:Why is the Firebase Realtime Database's data appearing as null in the console?为什么 Firebase 实时数据库的数据在控制台中显示为空? 【发布时间】:2021-09-02 15:35:36 【问题描述】:

我正在尝试创建一个简单的应用程序,该应用程序将帖子添加到 firebase 实时数据库并在颤动的列表视图中显示它们,但是当我将其“发布”到数据库时,在 firebase 控制台上,数据值不断显示为空值。有谁知道怎么回事?

这是我的一些代码 -

post.dart

class Post 
  Image coverImg;
  File audioFile;
  String body;
  String author;
  Set usersLiked = ;
  DatabaseReference _id;

  Post(this.body, this.author);

  void likePost(User user) 
    if (this.usersLiked.contains(user.uid)) 
      this.usersLiked.remove(user.uid);
     else 
      this.usersLiked.add(user.uid);
    
  

  void update() 
    updatePost(this, this._id);
  

  void setId(DatabaseReference id) 
    this._id = id;
  

  Map<String, dynamic> toJson() 
    return 
      'body': this.body,
      'author': this.author,
      'usersLiked': this.usersLiked.toList()
    ;
  


Post createPost(record) 
  Map<String, dynamic> attributes = 
    'author': '',
    'usersLiked': [],
    'body': ''
  ;

  record.forEach((key, value) => attributes[key] = value);

  Post post = new Post(attributes['body'], attributes['author']);
  post.usersLiked = new Set.from(attributes['usersLiked']);
  return post;


class PostList extends StatefulWidget 
  final List<Post> listItems;
  final User user;
  PostList(this.listItems, this.user);

  @override
  _PostListState createState() => _PostListState();


class _PostListState extends State<PostList> 
  void like(Function callBack) 
    this.setState(() 
      callBack();
    );
  

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

  @override
  void dispose() 
    super.dispose();
  

  @override
  Widget build(BuildContext context) 
    return ListView.builder(
      itemCount: this.widget.listItems.length,
      itemBuilder: (context, index) 
        var post = this.widget.listItems[index];

        return Card(
            elevation: 7.0,
            color: Colors.white,
            child: Column(
              children: [
                Row(
                  children: [
                    IconButton(
                      icon: Icon(
                        Icons.play_circle_outline,
                        color: Colors.black,
                        size: 30,
                      ),
                      onPressed: () ,
                    ),
                    Expanded(
                      child: ListTile(
                        title: Text(post.body,
                            style: TextStyle(
                                fontWeight: FontWeight.w600,
                                color: Colors.black)),
                        subtitle: Text(post.author,
                            style: TextStyle(color: Colors.black)),
                      ),
                    ),
                    Expanded(
                        child: Row(
                      mainAxisAlignment: MainAxisAlignment.end,
                      children: [
                        Text(post.usersLiked.length.toString(),
                            style: TextStyle(
                                color: Colors.black,
                                fontWeight: FontWeight.w600)),
                        IconButton(
                          icon: Icon(
                            Icons.thumb_up,
                            color: post.usersLiked.contains(widget.user.uid)
                                ? Colors.blue
                                : Colors.black,
                          ),
                          onPressed: () =>
                              this.like(() => post.likePost(widget.user)),
                        )
                      ],
                    ))
                  ],
                )
              ],
            ));
      ,
    );
  

database.dart

final databaseReference = FirebaseDatabase.instance.reference();

DatabaseReference savePost(Post post) 
  var id = databaseReference.child('posts/').push();
  id.set(post.toJson());
  return id;


void updatePost(Post post, DatabaseReference id) 
  id.update(post.toJson());


Future<List<Post>> getAllPosts() async 
  DataSnapshot dataSnapshot = await databaseReference.child('posts/').once();
  List<Post> posts = [];
  if (dataSnapshot.value != null) 
    dataSnapshot.value.forEach((key, value) 
      Post post = createPost(value);
      post.setId(databaseReference.child('posts/' + key));
      posts.add(post);
    );
  
  return posts;

home.dart

class UserInfoScreen extends StatefulWidget 
  const UserInfoScreen(Key key, User user)
      : _user = user,
        super(key: key);

  final User _user;

  @override
  _UserInfoScreenState createState() => _UserInfoScreenState();


class _UserInfoScreenState extends State<UserInfoScreen> 
  User _user;
  bool _isSigningOut = false;
  List<Post> posts = [];

  void newPost(String text) 
    var post = new Post(text, widget._user.displayName);
    post.setId(savePost(post));
    this.setState(() 
      posts.add(post);
    );
  

  void updatePosts() 
    getAllPosts().then((posts) => 
          this.setState(() 
            this.posts = posts;
          )
        );
  

  Route _routeToSignInScreen() 
    return PageRouteBuilder(
      pageBuilder: (context, animation, secondaryAnimation) => SignInScreen(),
      transitionsBuilder: (context, animation, secondaryAnimation, child) 
        var begin = Offset(-1.0, 0.0);
        var end = Offset.zero;
        var curve = Curves.ease;

        var tween =
            Tween(begin: begin, end: end).chain(CurveTween(curve: curve));

        return SlideTransition(
          position: animation.drive(tween),
          child: child,
        );
      ,
    );
  

  @override
  void initState() 
    _user = widget._user;

    // HOME PAGE

    pageList.add(Scaffold(
      backgroundColor: Colors.white,
      body: Column(children: [
        Expanded(
          child: PostList(this.posts, _user),
        ),
      ]),
    ));

    pageList.add(Test1());

    pageList.add(Scaffold(
      backgroundColor: Colors.white,
      body: Column(
        children: [
          TextInputWidget(this.newPost, "Title:"),
        ],
      ),
    ));

    pageList.add(Test3());

    // ACCOUNT PAGE

    pageList.add(
      Scaffold(
        backgroundColor: Colors.white,
        body: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: [
            Row(),
            _user.photoURL != null
                ? ClipOval(
                    child: Material(
                      color: Colors.grey.withOpacity(0.3),
                      child: Image.network(
                        _user.photoURL,
                        fit: BoxFit.fitHeight,
                      ),
                    ),
                  )
                : ClipOval(
                    child: Material(
                      color: Colors.grey.withOpacity(0.3),
                      child: Padding(
                        padding: const EdgeInsets.all(16.0),
                        child: Icon(
                          Icons.person,
                          size: 60,
                          color: Colors.black,
                        ),
                      ),
                    ),
                  ),
            SizedBox(height: 16.0),
            Text(
              '$_user.displayName',
              style: TextStyle(
                  color: Colors.black,
                  fontSize: 26,
                  fontWeight: FontWeight.w700),
            ),
            SizedBox(height: 8.0),
            Text(
              ' $_user.email ',
              style: TextStyle(
                color: Colors.black,
                fontSize: 20,
                letterSpacing: 0.5,
              ),
            ),
            SizedBox(height: 60.0),
            _isSigningOut
                ? CircularProgressIndicator(
                    valueColor: AlwaysStoppedAnimation<Color>(Colors.white),
                  )
                : ElevatedButton(
                    style: ButtonStyle(
                      backgroundColor: MaterialStateProperty.all(
                        Colors.redAccent,
                      ),
                      shape: MaterialStateProperty.all(
                        RoundedRectangleBorder(
                          borderRadius: BorderRadius.circular(10),
                        ),
                      ),
                    ),
                    onPressed: () async 
                      setState(() 
                        _isSigningOut = true;
                      );
                      await Authentication.signOut(context: context);
                      setState(() 
                        _isSigningOut = false;
                      );
                      Navigator.of(context)
                          .pushReplacement(_routeToSignInScreen());
                    ,
                    child: Padding(
                      padding: EdgeInsets.only(top: 8.0, bottom: 8.0),
                      child: Text(
                        'Logout',
                        style: TextStyle(
                          fontSize: 20,
                          fontWeight: FontWeight.w500,
                          color: Colors.white,
                        ),
                      ),
                    ),
                  ),
          ],
        ),
      ),
    );

    super.initState();
    updatePosts();
  

  @override
  List<Widget> pageList = List<Widget>();
  int _currentIndex = 0;

  void onTabTapped(int index) 
    setState(() 
      _currentIndex = index;
    );
  

  Widget build(BuildContext context) 
    return Scaffold(
      appBar: AppBar(
        elevation: 0.0,
        backgroundColor: Colors.white,
        title: Text(
          'SoundFX',
          style: TextStyle(color: Colors.black),
        ),
        centerTitle: true,
      ),
      body: IndexedStack(
        index: _currentIndex,
        children: pageList,
      ),
      bottomNavigationBar: BottomNavigationBar(
        unselectedItemColor: Colors.grey,
        selectedItemColor: Colors.blue,
        backgroundColor: Colors.white,
        elevation: 19.0,
        onTap: onTabTapped,
        currentIndex: _currentIndex,
        type: BottomNavigationBarType.fixed,
        items: [
          BottomNavigationBarItem(
              icon: new Icon(Icons.home),
              title: Container(
                height: 1.0,
              )),
          BottomNavigationBarItem(
              icon: new Icon(Icons.search),
              title: Container(
                height: 1.0,
              )),
          BottomNavigationBarItem(
              icon: new Icon(
                Icons.add_circle,
                size: 40,
              ),
              title: Container(
                height: 1.0,
              )),
          BottomNavigationBarItem(
              icon: new Icon(Icons.videocam),
              title: Container(
                height: 1.0,
              )),
          BottomNavigationBarItem(
              icon: Icon(Icons.account_circle),
              title: Container(
                height: 1.0,
              )),
        ],
      ),
    );
  





class Test1 extends StatelessWidget 
  @override
  Widget build(BuildContext context) 
    return Container(
      color: Colors.green,
    );
  


class Test2 extends StatelessWidget 
  @override
  Widget build(BuildContext context) 
    return Container(
      color: Colors.blue,
    );
  


class Test3 extends StatelessWidget 
  @override
  Widget build(BuildContext context) 
    return Container(
      color: Colors.yellow,
    );
  

text-input.dart

class TextInputWidget extends StatefulWidget 
  final Function(String) callback;
  String label;

  TextInputWidget(this.callback, this.label);

  @override
  _TextInputWidgetState createState() => _TextInputWidgetState();


class _TextInputWidgetState extends State<TextInputWidget> 
  final controller = TextEditingController();

  @override
  void dispose() 
    super.dispose();

    controller.dispose();
  

  void click() 
    widget.callback(controller.text);
    FocusScope.of(context).unfocus();
    controller.clear();
  

  void pickFiles() async 
    FilePickerResult result =
        await FilePicker.platform.pickFiles(type: FileType.any);

    File file = File(result.files.first.path);
    print(file);
  

  @override
  Widget build(BuildContext context) 
    return Container(
      height: 400,
      child: Column(
        mainAxisSize: MainAxisSize.min,
        children: [
          Expanded(
            child: Container(
                padding: EdgeInsets.all(20.0),
                child: TextField(
                    controller: this.controller,
                    decoration: InputDecoration(
                      labelText: this.widget.label,
                    ))),
          ),
          Container(
            child: ElevatedButton(onPressed: this.click, child: Text('Post')),
          ),
          Container(
            child:
                ElevatedButton(onPressed: this.pickFiles, child: Text('test')),
          )
        ],
      ),
    );
  

PS:另外,请注意,有些函数和类是未使用或基本没用的,有些名称非常愚蠢,但如果它们与问题无关,请不要评论,因为那些只是对我要添加到应用程序中的功能进行一些测试。

另外,请注意我遵循了本教程 - https://www.youtube.com/playlist?list=PLzMcBGfZo4-knQWGK2IC49Q_5AnQrFpzv

【问题讨论】:

我会看看会发生什么,但遵循 how to create a minimal, complete, verifiable example 中的指导确实是您可以做的最好的事情,以增加有人可以提供帮助的机会。 通过快速扫描,这是我看到您写入数据库的主要位置:id.set(post.toJson());。 1)当该行运行时,是否有任何内容写入调试输出? 2) 如果将其更改为id.set("hello world");,它会写入数据库吗? 3)id.update(post.toJson());中的id在哪里定义? @FrankvanPuffelen 1) 不,我什么都没看到,2) 更改后什么也没写,3) id 直接在 database.dart 的 savePost() 函数中定义 3) 我问过updatePost ;-) 1) 嗯...您确定您的设备已连接到网络/数据库吗?如果是这样,您的数据库在哪里? @FrankvanPuffelen 哈哈,抱歉,在 updatePost 中它位于 Post 类中。嗯,你说的连接是什么意思?我正在使用 ios 模拟器,很明显,我的网络正在运行。但是我的数据库位于新加坡,或者 asia-southeast1 【参考方案1】:

firebaser 在这里

Firebase SDK 很可能无法从其配置文件中读取数据库的 URL,因为您的数据库托管在默认(美国)区域之外。

如果确实是这个原因,您应该在代码中指定数据库 URL。通过在代码中指定它,SDK 应该能够连接到数据库实例,无论它托管在哪个区域。

这意味着你应该得到你的数据库

FirebaseDatabase("your database URL").reference()
// Or
FirebaseDatabase(databaseURL: "your database URL").reference()

而不是

FirebaseDatabase.instance.reference()

记录在here:

要获取对 us-central1 默认 dstabase 以外的数据库的引用,您必须将数据库 URL 传递给 getInstance()(或 Kotlin+KTX database())。对于 us-central1 默认数据库,您可以不带参数调用 getInstance()(或数据库)。

因此,虽然这个 已记录在案,但它非常容易被忽视。我正在与我们的团队确认是否有什么办法可以让这个配置问题更加明显。

【讨论】:

哇!太感谢了。是的,它确实有效,但由于某种原因,这些帖子没有显示在列表视图中......你知道可能是什么问题吗? 这似乎是一个不同的问题,所以我建议使用自己的minimal reproduction 发布一个新问题。

以上是关于为啥 Firebase 实时数据库的数据在控制台中显示为空?的主要内容,如果未能解决你的问题,请参考以下文章

为啥注册用户后 Firebase 实时数据库用户 ID 与 Firebase 身份验证 UID 不匹配?

Firebase 实时数据库 setValue() 不工作

如何手动更改firebase实时数据库、数据类型?

JAVA Android Studio 不向 Firebase 实时数据库发送数据

如何使用 Firebase 实时数据库?

如何使用firebase实时数据库ios增加特定节点中的值