1

I know this question is asked and answered many times but my problem is a bit different. I am working with firebase realtime database in flutter. I upload a JSON file in the database for the existing data I have. It looks like this

Each child has 4 properties (Name, Location, Quality, Size) The children have IDs of 0,1,2..... When I retrieve this database in my app, it works and it is displayed perfectly.

When I create a new entry from my app, the child has a random ID and it looks like this.

After that when I try to retrieve the values, the values are printed in the console but on the screen I get:-

The method [] was called on null error. Receiver: null. Tried Calling: []("Name")

. The Error screen looks like this. Error in console looks like this

My code for retrieving (I fetch and pass the variable to another screen):-

              ref.once().then((DataSnapshot data) {
                datatosend = data;
                print(datatosend.value);
                Navigator.push(
                    context,
                    MaterialPageRoute(
                      builder: (context) => DisplayList(
                          text: datatosend,
                          title: CategoryItemsitems[index].name),
                    ));
              });

My code for displaying listview:

                  itemCount: widget.text.value.length,
                  itemBuilder: (BuildContext context, int index) {
                    return Padding(
                      padding: const EdgeInsets.all(8.0),
                      child: ListTile(
                        leading: IconButton(
                            icon: Icon(Icons.edit),
                            onPressed: () {
                              print("Edit Pressed!");
                            }),
                        title: Text(widget.text.value[index]["Name"]),
                        subtitle: Text("Quality: " +
                            widget.text.value[index]["Quality"] +
                            "\nSize: " +
                            widget.text.value[index]["Size"] +
                            "\nLocation: " +
                            widget.text.value[index]["Location"]),
                        trailing: IconButton(
                            icon: Icon(
                              Icons.delete,
                              color: Colors.red,
                            ),
                            onPressed: () {
                              print("Delete Pressed!");
                            }),
                      ),
                    );
                  }),

My code for creating a new entry:

databaseReference.child(_category).push().set({
                        "Name": _name,
                        "Quality": _quality,
                        "Size": _size,
                        "Location": _location
                      }).then((_) {
                        Scaffold.of(context).showSnackBar(
                            SnackBar(content: Text('Successfully Added')));
                      });

Where am I going Wrong?

Aaditya Joshi
  • 122
  • 10
  • Did it not give you a line number or stacktrace for that error? – nvoigt Sep 18 '20 at 05:42
  • I have added the image of error in console. It points to line 37 which is this one : ```title: Text(widget.text.value[index]["Name"]),``` – Aaditya Joshi Sep 18 '20 at 05:52
  • 1
    Okay then, what exactly is the question? Your runtime says `widget.text.value[index]` was `null`. How that came to be would be your job to find out, probably through debugging your application. – nvoigt Sep 18 '20 at 05:54

2 Answers2

0

Hard to know without having access to the code, but this is usually what I do when I run into this type of issues:

  • run the code in debug mode and put a breaking right after this line: itemBuilder: (BuildContext context, int index) {. This way you can introspect widget.text.value and see if it's really the array of objects you expected.

  • otherwise, use a good old print and start printing widget.text.value[index] in your itemBuilder (or even start by printing widget.text, then widget.text.value). You would be surprised how man bugs got figured out with a low-tech print function over the years ;-)

Good luck

Didier Prophete
  • 1,834
  • 1
  • 12
  • 11
  • In my retrieval code, you can see that I have added a print statement ```print(datatosend.value); ``` which prints correct values in the console. When I change code to ```print(datatosend.value[0]); ``` or ```print(datatosend.value); ```, I get the error. – Aaditya Joshi Sep 18 '20 at 12:48
  • Ok, so what is the type of `datatosend.value` specifically? Looks like you are expecting it to be an array of objects. Can you use the debugger to verify that this is indeed the case? – Didier Prophete Sep 18 '20 at 14:44
  • ```datatosend.value``` has a type of DataSnapshot – Aaditya Joshi Sep 19 '20 at 05:20
  • Ah, then this explains why you can't do `datatosend.value[item]`. If you check the official api here https://firebase.google.com/docs/reference/js/firebase.database.DataSnapshot, you will see that you need to call `datatosend.value.val()` to get the value out of a `DataSnapshot`. So this should work: `datatosend.value.val()[index]` – Didier Prophete Sep 19 '20 at 15:09
  • When I try ```print(datatosend.value.val());``` or ```print(datatosend.value.val()[index]);``` or ```print(datatosend.value.val()[index]["Name"]);``` I get the following error: ```[ERROR:flutter/lib/ui/ui_dart_state.cc(157)] Unhandled Exception: NoSuchMethodError: Class '_InternalLinkedHashMap' has no instance method 'val'. Receiver: _LinkedHashMap len:4 Tried calling: val() ``` – Aaditya Joshi Sep 20 '20 at 05:01
  • so are you sure that `datatosend.value` has the type `DataSnapshot` ? Because according to the official doc, it should have a `val()` method. But otherwise this error tells you that `datatosend.value` behaves like a hashmap. So your array is probably in one of the fields of this hashmap. Just put a breakpoint and introspect the different field and you should find your array. – Didier Prophete Sep 20 '20 at 05:51
  • The thing that bothers me is that my original code (posted above) was working. It only breaks when I create a new entry from my app. Anyways, thanks for all your help. I have other projects also. I will keep working on this and tell you what happens. – Aaditya Joshi Sep 21 '20 at 04:43
0

After about 10 days, my problem is finally solved. Some changes I made:

  1. Instead of using, realtime database I am using Cloud Firestore.
  2. Instead of importing the JSON file, I will enter the data manually. Fortunately, it is not very big and earlier also I was writing in the JSON file manually only.

Code to add the data to Firestore. All of this is inside the "onpressed" parameter of a button. All the inputs are taken by a simple form.

firestoreInstance.collection("cars").add({
                              "Name": _name,
                              "Quality": _quality,
                              "Size": _size,
                              "Location": _location,
                            }).then((value) {
                            print("Added Successfully")});

For fetching the data and access its different fields I am using a stream-builder:

StreamBuilder(
            stream: Firestore.instance
                .collection("cars")
                .orderBy("Name")   //To display the list by Name
                .snapshots(),
            builder: (context, snapshot) {
              if (!snapshot.hasData) {
                return Center(child: CircularProgressIndicator());
              } 
              else {
                if(snapshot.data.documents.length>0)
                {
                  return ListView.builder(
                     itemCount: snapshot.data.documents.length,   //no. of entries fetched
                    itemBuilder: (BuildContext context, int index) {
                      return ListTile(
                        title: Text(
                            snapshot.data.documents[index].data()["Name"]),  //Accessing the Name property
                        subtitle: Text("Quality: " +snapshot.data.documents[index].data()["Quality"] +   //Accessing the Quality property

                        "\nSize: " +snapshot.data.documents[index].data()["Size"] +   //Accessing the Size property

                        "\nLocation: " +snapshot.data.documents[index].data()["Location"])   //Accessing the Location property

                      );
                }
                  )}
                }
              }
              }
)

I apologize if some of the closing parenthesis does not match. I pulled these important snippets from my very messy code.

Aaditya Joshi
  • 122
  • 10