I have an app that has 2 pages. The first page lists all records. If a user clicks on an item in the list the user is then taken to the second page, that should display the record's details. The app compiles without error but in the Simulator if I try clicking on one of the links on the 1st page then I get the following error:
NoSuchMethodError: The getter 'data' was called on null.
Receiver: null
Tried calling: data
Please see the code below (I tried putting the StreamBuilder high up the hierarchy so that it's not possible to get a null error).
Please can someone point me in the right direction? Thanks
void main() async {
WidgetsFlutterBinding.ensureInitialized();
await Firebase.initializeApp(options: DefaultFirebaseOptions.currentPlatform);
runApp(Home());
}
class Home extends StatelessWidget {
// const Home({Key? key}) : super(key: key);
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Demo',
theme: ThemeData(
primarySwatch: Colors.blue,
),
routes: {
'/': (context) => ItemList(),
'/factfile': (context) => ItemDetails(),
},
);
}
}
class ItemList extends StatelessWidget {
ItemList({Key? key}) : super(key: key) {
_stream = _reference.snapshots();
}
CollectionReference _reference = FirebaseFirestore.instance.collection('table_name');
late Stream<QuerySnapshot> _stream;
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('Item List'),
),
body: StreamBuilder<QuerySnapshot>(
stream: _stream,
builder: (BuildContext context, AsyncSnapshot snapshot) {
//Check error
if (snapshot.hasError) {
return Center(child: Text('Some error occurred ${snapshot.error}'));
}
//Check if data arrived
if (snapshot.hasData) {
//get the data
QuerySnapshot querySnapshot = snapshot.data;
List<QueryDocumentSnapshot> documents = querySnapshot.docs;
//Convert the documents to Maps
List<Map> items = documents.map((e) =>
{
'name': e['name'],
'dlastupd': e['dlastupd'],
'dlastupd date': DateTime.fromMillisecondsSinceEpoch(e['dlastupd'] * 1000),
'id': e['id'],
}).toList();
// sort in descending date order
items.sort((a, b) => b["dlastupd"].compareTo(a["dlastupd"]));
//Display the list
return ListView.builder(
itemCount: items.length,
itemBuilder: (BuildContext context, int index) {
//Get the item at this index
Map thisItem = items[index];
//Return the widget for the list items
return ListTile(
title: Text(formatDate(thisItem['dlastupd date'], [dd, '', M]) + " - " + thisItem['name']),
onTap: () {
Navigator.pushNamed(
context,
'/factfile',
arguments: {
'id': thisItem['id'],
},
);
},
);
});
}
//Show loader
return Center(child: CircularProgressIndicator());
},
), //Display a list // Add a FutureBuilder
);
}
}
class ItemDetails extends StatelessWidget {
// final String itemId;
Map routeData = {};
// ItemDetails(this.itemId, {Key? key}) : super(key: key);
@override
Widget build(BuildContext context) {
routeData = ModalRoute
.of(context)
?.settings
.arguments as Map;
print(routeData);
final DocumentReference docRef =
FirebaseFirestore.instance.collection(“table_name”).doc(routeData['id']);
var snapshot;
final data = snapshot.data!.data() as Map<String, dynamic>;
return FutureBuilder<DocumentSnapshot>(
future: docRef.get(),
builder: (context, snapshot) {
if (snapshot.connectionState == ConnectionState.waiting) {
return Scaffold(
appBar: AppBar(
title: Text("Waiting for future..."),
),
body: Center(child: CircularProgressIndicator()),
);
} else if (snapshot.hasError) {
return Scaffold(
appBar: AppBar(
title: Text("Error"),
),
body: Center(child: Text("Error: ${snapshot.error}")),
);
} else {
return Scaffold(
appBar: AppBar(
title: Text(data?["name"]),
),
body: Center(child: Text("Data has been loaded")),
);
}
},
);
}
}
I took a quicklook, but it seems there's something missed:
In your build method after extraction of your passed data. snapshot is declared but not initialized, it's null and you are trying to access data (the compiler warned you but you used exclamation operator to claim that snapshot is not null).
var snapshot;
final data = snapshot.data!.data() as Map<String, dynamic>;
So, figure out the purpose of the snapshot and fix it.
Hope it helps you.