I have an null safety issue with my StreamBuilder in my flutter app.
On the open bracket "{" of the builder: property I am getting this error The body might complete normally, causing 'null' to be returned, but the return type is a potentially non-nullable type.
Here is the code for the StreamBuilder.
StreamBuilder (
stream: _db.collection('agency').doc(globals.agencyId).
collection('trxns').doc(globals.currentTrxnId).snapshots(),
builder: (BuildContext context, AsyncSnapshot trxnSnapshot) {
if (trxnSnapshot.hasData) {
var outPut = (trxnSnapshot.data() as QueryDocumentSnapshot);
clientFNameController.text = trxnSnapshot.data.data['clientFName'] ?? "";
}
),
I tried to add a type like this: StreamBuilder ( but I get this error: The argument type 'Stream<DocumentSnapshot<Map<String, dynamic>>>' can't be assigned to the parameter type 'Stream<QuerySnapshot<Object?>>?'.
Now I change the type to match the statement above and now I am back at the original error message. Here is what I changed the type to.
StreamBuilder <DocumentSnapshot<Map<String, dynamic>>>(
stream: _db.collection('agency').doc(globals.agencyId).
collection('trxns').doc(globals.currentTrxnId).snapshots(),
builder: (BuildContext context, AsyncSnapshot trxnSnapshot) {
if (trxnSnapshot.hasData) {
var outPut = (trxnSnapshot.data() as QueryDocumentSnapshot);
clientFNameController.text = trxnSnapshot.data.data['clientFName'] ?? "";
}
),
I don't know what is wrong or how to fix it. I know I need either this "!" or this "?" but I don't know which one or where to put it.
I would really appreciate some help here.
A StreamBuilder
must return a Widget in its builder
parameter. If you don't need to show any Widget (just do some background update), you can use a StreamSubscription
instead:
class _MyWidgetState extends State<MyWidget> {
late final StreamSubscription<DocumentSnapshot> _subscription;
@override
void initState() {
super.initState();
final Stream<DocumentSnapshot> stream = _db
.collection('agency')
.doc(globals.agencyId)
.collection('trxns')
.doc(globals.currentTrxnId)
.snapshots();
_subscription = stream.listen((data) {
if (data == null) return;
setState(() => clientFNameController.text = data['clientFName'] ?? "");
});
}
@override
void dispose() {
_subscription.cancel();
super.dispose();
}
}
However, if you want to keep using StreamBuilder
, you can
StreamBuilder(
stream: _db
.collection('agency')
.doc(globals.agencyId)
.collection('trxns')
.doc(globals.currentTrxnId)
.snapshots(),
builder: (BuildContext context, AsyncSnapshot trxnSnapshot) {
if (trxnSnapshot.hasData) {
var outPut = (trxnSnapshot.data as QueryDocumentSnapshot);
clientFNameController.text = outPut.data['clientFName'] ?? "";
}
return SizedBox.shrink();
},
),
StreamBuilder(
stream: _db
.collection('agency')
.doc(globals.agencyId)
.collection('trxns')
.doc(globals.currentTrxnId)
.snapshots(),
builder: (BuildContext context, AsyncSnapshot trxnSnapshot) {
if (trxnSnapshot.hasData) {
var outPut = (trxnSnapshot.data as QueryDocumentSnapshot);
clientFNameController.text = outPut.data['clientFName'] ?? "";
return Text("client name updated");
}
return Text("client name not updated");
},
),