Home > Net >  Flutter Firebase The method 'data' was called on null
Flutter Firebase The method 'data' was called on null

Time:11-04

I'm using Firestore and I tried to get streams by Streambuilder. However, This error happened.

The following NoSuchMethodError was thrown building StreamBuilder<DocumentSnapshot<Object>> 
(dirty, state: _StreamBuilderBaseState<DocumentSnapshot<Object>, 
AsyncSnapshot<DocumentSnapshot<Object>>>#32fdb):
The method 'data' was called on null.
Receiver: null
Tried calling: data()

And this is my code.

    import 'package:cloud_firestore/cloud_firestore.dart';
    import 'package:flutter/material.dart';
    
    class UserDetailPage extends StatefulWidget {
      String uid;
      UserDetailPage(this.uid);
    
      @override
      _UserDetailPageState createState() => _UserDetailPageState();
    }
    
    class _UserDetailPageState extends State<UserDetailPage> {
      final List<String> datas = <String>['a', 'b', 'c', 'd', 'e', 'f', 'g', '1', '2','3', '4', '5', '6'];
      CollectionReference userstream = FirebaseFirestore.instance.collection('users');
    
      @override
      void initState() {
        super.initState();
    
      }
    
    
      @override
      Widget build(BuildContext context) {
        return Scaffold(
          appBar: AppBar(
            title: Text('User Detail'),
          ),
          body:_buildBody(),
        );
      }
    
     _buildBody() {
    
        return StreamBuilder(
          stream: userstream.doc(widget.uid).snapshots(),
          builder: (context, snapshot){
            Map<String, dynamic> user_data =snapshot.data.data();
            if(snapshot.hasError){
              return Text('ERROR');
            }
            if (snapshot.connectionState == ConnectionState.waiting) {
              return Center(child: CircularProgressIndicator());
            }
    
            return Padding(
              padding: const EdgeInsets.all(20.0),
              child: ListView.separated(
                padding: EdgeInsets.only(left: 20, right: 20),
                itemCount: 13,
                separatorBuilder: (BuildContext context, int index) => const Divider(),
                itemBuilder: (BuildContext context, int index){
                  return Center(
                    child: Container(
                      child: Row(
                        mainAxisAlignment: MainAxisAlignment.spaceAround,
                        children: [
                          Text(datas[index]),
                          Text(user_data[datas[index]] is int?user_data[datas[index]].toString():user_data[datas[index]])
                        ],
                      ),
                    ),
                  );
                }
              )
            );
          },
        );
      }
    }

Interesting thing is that Immediately after this error occurs, the result I wanted appears on the app. So I thought the problem occurs in initstate() but I dont know exactly what is wrong.

By the way, this Page is called from

UserDetailPage( doc.get('uid')!=null?doc.get('uid'):'5AJUsH5LYaQcBiTtO5MA7d6OKx72');

CodePudding user response:

The AsyncSnapshot wraps data that is loaded asynchronously. Calling snapshot.data without checking whether the data is available (as you do in the code below), means you are ignoring this fact and might as well not use a StreamBuilder:

  stream: userstream.doc(widget.uid).snapshots(),
  builder: (context, snapshot){
    Map<String, dynamic> user_data =snapshot.data.data();

The proper way to deal with the stream is shown in the FlutterFire documentation on realtime listeners. The required change for you is that you only call snapshot.data after all the checks, instead of before them:

  builder: (context, snapshot){
    if(snapshot.hasError){
      return Text('ERROR');
    }
    if (snapshot.connectionState == ConnectionState.waiting) {
      return Center(child: CircularProgressIndicator());
    }
    Map<String, dynamic> user_data =snapshot.data.data();
  
  • Related