I get this error in the StreamBuilder
:
Here's the code:
import 'dart:async';
import 'package:firebase_database/firebase_database.dart';
import 'package:flutter/material.dart';
class NewCauseMenu extends StatefulWidget {
String? area;
NewCauseMenu(this.area, {super.key});
@override
State<NewCauseMenu> createState() => _NewCauseMenuState();
}
class _NewCauseMenuState extends State<NewCauseMenu> {
final db = FirebaseDatabase.instance;
String? dropdownValue;
String? problem;
String? causa1;
String? causa2;
String? causa3;
String? causa4;
var setDefaultProblem = true, setDefaultCauseOne = true;
@override
Widget build(BuildContext context) {
final myRef = db.ref();
return WillPopScope(
onWillPop: () {
return _onWillPopScope();
},
child: SafeArea(
child: Scaffold(
appBar: AppBar(
title: Text('Menú Nueva Causa ${widget.area}'),
),
body: Center(
child: Column(
children: [
const SizedBox(
height: 25,
),
StreamBuilder(
stream: myRef.child(widget.area.toString()).onValue,
builder: (context, snapshot) {
if (!snapshot.hasData) return Container();
final data = Map<String, dynamic>.from(
(snapshot.data)!.snapshot.value as Map);
if (setDefaultProblem) {
problem = data.keys.first.toString();
}
return DropdownButton(
value: problem,
icon: const Icon(Icons.arrow_downward),
isExpanded: false,
elevation: 16,
underline: Container(
height: 2,
color: Colors.blueAccent,
),
items: data.keys.map(((e) {
return DropdownMenuItem(
value: e.toString(), child: Text(e.toString()));
})).toList(),
onChanged: (value) {
setState(() {
problem = value!;
setDefaultProblem = false;
setDefaultCauseOne = true;
});
},
);
}),
const SizedBox(
height: 25,
),
problem != null
? StreamBuilder(
stream: myRef
.child(widget.area.toString())
.child(problem.toString())
.onValue,
builder: (context, snapshot) {
final data = Map<String, dynamic>.from(
(snapshot.data!.snapshot.value as Map));
if (!snapshot.hasData) {
debugPrint('snapshot status: ${snapshot.error}');
return Text(
'snapshot empty problem: $problem causa #1: $causa1');
}
debugPrint(data.toString());
if (setDefaultCauseOne) {
causa1 = data.keys.first.toString();
}
return DropdownButton(
value: causa1,
icon: const Icon(Icons.arrow_downward),
isExpanded: false,
elevation: 16,
underline: Container(
height: 2,
color: Colors.blueAccent,
),
items: data.keys.map(((e) {
return DropdownMenuItem(
value: e.toString(), child: Text(e.toString()));
})).toList(),
onChanged: (value) {
setState(() {
causa1 = value!;
setDefaultCauseOne = false;
});
},
);
},
)
: Text('problem null problem: $problem causa #1: $causa1')
],
),
),
)),
);
}
Future<bool> _onWillPopScope() async {
Navigator.of(context).pop();
return false;
}
}
I don't know why in the second StreamBuilder
there's a Null value in the snapshot.data
. I defined the var problem
in the first StreamBuilder
and it should work with the second one. But it doesn't.
When I run the program, happens this:
After the error, it seems that the app works perfectly.
I verified that the var problem
must get a value, otherwise the second StreamBuilder
doesn't work. I give a value for the var getting the first key of the snapshot.data
but for some reason in the beginning there's no value. That's the root of the problem. Help me, please. I don't know what to do.
CodePudding user response:
The "null pointer" exception is thrown when you try to access a property or call a method on an object that is null. In your code, it looks like this happens on the line
final data = Map<String, dynamic>.from((snapshot.data!.snapshot.value as Map));
where you try to access the "data" attribute of the "snapshot".
Here's the problem: In a Firebase stream, if no data is received, then snapshot.data
will be null. So if there is no data, you should not try to access snapshot.data
. You can get around this by adding an if (snapshot.data != null)
check before trying to access snapshot.data
.
So your code should look like this in the second StreamBuilder
:
if (!snapshot.hasData) {
debugPrint('snapshot status: ${snapshot.error}');
return Text('snapshot empty problem: $problem causa #1: $causa1');
}
final data = Map<String, dynamic>.from((snapshot.data!.snapshot.value as Map));
CodePudding user response:
just change the position and add new condition same as below
if (!snapshot.hasData || snapshot.data == null) {
debugPrint('snapshot status: ${snapshot.error}');
return Text(
'snapshot empty problem: $problem causa #1: $causa1');
}
final data = Map<String, dynamic>.from(
(snapshot.data!.snapshot.value as Map));
debugPrint(data.toString());
if (setDefaultCauseOne) {
causa1 = data.keys.first.toString();
}