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();