Wie erkenne ich, ob meine App mit Firebase verbunden ist?
Moin zusammen, ich gucke mir zurzeit eine Videoreihe auf Youtube an, in der man die Basics von Flutter lernt anhand der Programmierung einer To-Do-Liste. Ich bekomme bei 2 Methoden folgende Fehlermeldung:
NoSuchMethodError: The method "getTodos" was called on null.
Receiver: null
Tried calling: getTodos
Das ist die Methode addItem, sie bekommt einen String und soll mit diesem dann die Methode setTodos aus der Databaseklasse aufrufen.
setTodos() soll dann auf die Collection in Firestore zugreifen und auf das Dokument mit der passenden UserID zugreifen. Dann soll er den String inkl. dem bool einspeichern.
Das soll der Ablauf sein, und ich finde, die einzige Möglichkeit wo ein Fehler auftreten kann ist die, dass ich keinen Zugriff auf die Collection in Firestore habe oder da was schiefläuft.
Bei der Methode getTodos(), sollen mir die Einträge eines Dokuments gegeben werden.
Falls ihr mehr Code braucht sagt bitte bescheid :)
die passende json-Datei die benötigt ist habe ich in meinem Projekt integriert und die ApplicationID ist auch identisch.
Danke
1 Antwort
Anhand deiner Screenshots ist nicht ersichtlich, ob du die Variable database jemals irgendwo definierst. Die Fehlermeldung jedenfalls deutet an, dass du das nicht tust. So zeigt die Variable auf null. Dieses nicht-existente Objekt hat natürlich keine Methode getTodos.
Und wird dieser Teil zu hundert Prozent vor dem ersten Aufruf von getTodos ausgeführt?
Ich kann die App leider nicht debuggen, sobald createState() => aufgerufen wird, springt er raus und gibt mir diese Meldung.
Future<void> connectToFirebase() async{
//The firebase toolbox for authenticate
final FirebaseAuth authenticate = FirebaseAuth.instance;
//Session is persist for this adivice, uid will stay the same
UserCredential result = await authenticate.signInAnonymously();
user = result.user;
database = DatabaseService(user.uid);
if(!(await database.checkIfUserExists())){
database.setTodo("Todo anlegen", false);
//ShowDialog machen
}
Stream userDocumentStream = database.getTodos();
userDocumentStream.listen( (documentSnapshot) =>
print(documentSnapshot.data) );
}
Das ist der Code der ganzen Methode
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text("To-Do-Liste"),
centerTitle: mounted,
backgroundColor: Color.fromRGBO(35, 152, 185, 100),),
body: FutureBuilder(
future: connectToFirebase(),
builder: (BuildContext context, AsyncSnapshot snapshot){
if(snapshot.connectionState == ConnectionState.waiting){
return Center(child: CircularProgressIndicator());
}else{
return StreamBuilder<DocumentSnapshot>(
stream: database.getTodos(),
builder: (
context, AsyncSnapshot<DocumentSnapshot> snapshot) {
if (!snapshot.hasData) {
return Center(child: CircularProgressIndicator());
} else {
Map<String, dynamic> items = snapshot.data.data();
return ListView.builder(
es wird die getTodos() allerdings hier auch aufgerufen. Ich weiß, nicht was zuerst verarbeitet wird
future (wo du die Instanz erst definierst) wird asynchron irgendwann aufgerufen. Also wohl viel später, als der erste Aufruf des builder-Callbacks erfolgt. Erstelle das database-Objekt am besten schon beim Anlegen der Klasse _NewTaskState (?).
Dann kommen weitere Fehler bezüglich der Instanz und ich kann await nicht mehr verwenden, da dies mit async zusammen benutzt wird..
Der Fehler entsteht laut der Konsole in der Zeile:
stream: database.getTodos()
dabei ist wartet der FutureBuilder ja auf die Methode connectToFirebase(), welche ich oben bereits geschickt habe.
Also ist doch etwas in dieser Methode falsch..?
Folgende Fehler bedeuten im Umkehrschluss nicht zwingend, dass die vorherige Korrektur falsch war. Ein Fix kann auch mehrere notwendige Änderungen mit sich ziehen.
Ich habe ein wenig debuggt, es hat sich gezeigt, dass er einmal kurz in die connectToFirebase() springt aber nach der ersten Zeile direkt wieder rausspringt. Weshalb er dann im Scaffold auch den FutureBuilder komplett überspringt. Ich weiß allerdings nicht wieso.
Mit dem Code wird es definiert, hatte ich in meiner Erklärung oben vergessen..
Der Konstruktor für die Database-Klasse benötigt nur einen String(uid)