I am trying to learn how to use Firebase through a lesson on YT. But I cannot get it to work.
What happens:
- The " if (snapshot.hasError) is true and returns:
Something went wrong! type 'Null' is not a subtype f type 'String'
- But I can see in my Firebase console that it is trying to read/access the database.
- And i have checked that my Json names are corresponding to those in the firebase console.
My conclusion from that: My code is the problem. Specifically something about my readFruits function.
I cannot seem to figure out what I have missed. Can you see something I am missing or that I am doing wrong?
This is all of my code.
import 'package:flutter/material.dart';
import 'package:cloud_firestore/cloud_firestore.dart';
import 'package:firebase_core/firebase_core.dart';
Future main() async {
WidgetsFlutterBinding.ensureInitialized();
await Firebase.initializeApp();
runApp(const MyApp());
}
class MyApp extends StatelessWidget {
const MyApp({super.key});
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Demo',
theme: ThemeData(
primarySwatch: Colors.blue,
),
home: MyHomePage(title: 'Flutter Demo Home Page'),
);
}
}
class MyHomePage extends StatefulWidget {
MyHomePage({super.key, required this.title});
final String title;
@override
State<MyHomePage> createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text(widget.title),
),
body: StreamBuilder<List<Fruit>>(
stream: readFruits(),
builder: (context, snapshot) {
if (snapshot.hasError) {
return Text('Something went wrong! ${snapshot.error}');
} else if (snapshot.hasData) {
final fruit = snapshot.data!;
return ListView(
children: fruit.map(buildFruit).toList(),
);
} else {
return const Center(child: CircularProgressIndicator());
}
},
),
);
}
}
Stream<List<Fruit>> readFruits() => FirebaseFirestore.instance.collection('Fruits').snapshots().map(
(snapshot) => snapshot.docs.map((doc) => Fruit.fromJson(doc.data())).toList(),
);
Widget buildFruit(Fruit fruit) => ListTile(
title: Text(fruit.fruit),
subtitle: Text(fruit.colour),
);
class Fruit {
final String fruit;
final String colour;
const Fruit({required this.colour, required this.fruit});
static Fruit fromJson(Map<String, dynamic> json) => Fruit(
fruit: json['type'],
colour: json['colour'],
);
Map<String, dynamic> toJson() => {'type': fruit, 'colour': colour};
}
CodePudding user response:
I think your not accounting for null cases when your data is returned from Firebase. Try this:
static Fruit fromJson(Map<String, dynamic> json) => Fruit(
fruit: json['type'] ?? "",
colour: json['colour'] ?? "",
);
CodePudding user response:
The problem was that when I double-checked the JSON keys, I didn't notice that I had put them inside a map in the firebase console. So it is not weird that my code was nonfunctional.
I just thought the "Fruits" was a header...
Georgina's Answer would also have solved it if had more documents with some correct and some incorrect.