0

So I try to build Sliverlist on the first run I am hard-coding the child count to 20 (e.g.) and the app works just fine but if I try to set the childCount to the length of my FireStore collection on the first run i get the error

======== Exception caught by widgets library =======================================================
The following NoSuchMethodError was thrown building:
The getter 'length' was called on null.
Receiver: null
Tried calling: length

BUT! if I first set the childCount manually to 20 and then doing hot reload to the app with the childCount set to handlyCalls.length it works like it should, any suggestions?

class HandlyCallsList extends StatefulWidget {
@override
_HandlyCallsListState createState() => _HandlyCallsListState();
}

class _HandlyCallsListState extends State<HandlyCallsList> {
@override
Widget build(BuildContext context) {

  final handlyCalls = Provider.of<List<HandlyCall>>(context);
  int count = 20;

return SliverList(
  delegate: SliverChildBuilderDelegate(
        (BuildContext context, index) {
          print('!!!!!!!!!!!! 11111111111111111111 ${handlyCalls.length}');
      return HandlyCallTile(handlyCall: handlyCalls[index]);
    },
    childCount: handlyCalls.length,
  ),
);

UPDATE

this is the handyCall to list function

List<HandlyCall> _handlyCallListFromSnapshot(QuerySnapshot snapshot) {
return snapshot.docs.map((document) {
  return HandlyCall(
    title: document.data()['title'] ?? '',
    type: document.data()['type'] ?? '',
    reward: document.data()['reward'] ?? null,
    money: document.data()['money'] ?? 0,
    name: document.data()['name'] ?? '',
    rating: document.data()['rating'] ?? 25,
    user: document.data()['user'] ?? null,
  );
}).toList() ;
}

//get userProfile stream
Stream<List<HandlyCall>> get handlyCalls {
return handlyCallsCollection.snapshots().
map(_handlyCallListFromSnapshot);
}
Nitai Dan
  • 29
  • 1
  • 6
  • This means that `handlyCalls` is null. You can verify that it is null by adding this to your code: `print(handlyCalls);` handlyCalls should contain a value. In this case, it should be a List – CoderUni Mar 16 '21 at 14:51
  • So Iv'e printed the handlyCalls.length but immediately afterwards the Run console prints the error again, And it's only happens on the first Run cause when I do Hot Reload it's all good no errors are thrown – Nitai Dan Mar 16 '21 at 14:57
  • print handlyCalls not handlyCalls.length. The error means that handlyCalls is null, meaning that it contains no value. You need handlyCalls to contain a value. You need it to be of type List T is just a representation of type. Replace T with String, int, etc. – CoderUni Mar 16 '21 at 14:59
  • Did that and it printed my the list, it seems as the app doesn't wait until it get's the list from firebase, I tried to use 'await' but this is a widget and can't be asynchronous... – Nitai Dan Mar 16 '21 at 15:10
  • Use FutureBulder: https://www.youtube.com/watch?v=ek8ZPdWj4Qo and to avoid fetching data when rebuilding: https://stackoverflow.com/questions/57793479/flutter-futurebuilder-gets-constantly-called – CoderUni Mar 16 '21 at 15:15
  • put this line in the didChangeDependencies() method: final handlyCalls = Provider.of>(context); – Omar Fayad Mar 16 '21 at 15:16

2 Answers2

0

I'm not sure what the handlyCalls is like, but I think the best approach for you would be create the list inside one class that will be handled in the provider and contain a list of handlyCalls and not giving the provider a list of handlyCalls.

So would be like this:

    class handlyCallsList extends ChangeNotifier {
    
      List<handlyCalls> _list;
    
      List<handlyCalls> get list => _list;
    
      void changeList(List<handlyCalls> list){
        this._list = list;
        notifyListeners(); // Important to notify all the listeners and make the listeners refresh the view
      }
    }

Now you should initialize your provider with a default value so you can always have a list so it will not be null in the first run.

ChangeNotifierProvider<handlyCallsList>(
      create: (_) => handlyCallsList()..changeList([]), // you can add the default list here for when it loads the first time so you will not find it null
);

You can also check the value to see if it's null the list thats it's returning or check with handlyCalls?.length for possible null values.

Ayad
  • 671
  • 5
  • 16
  • Tried to do both the Future builder and the notifyListeners solutions and it didn't work I've taken another approach and I'll post it here – Nitai Dan Mar 16 '21 at 18:34
0

OK so after a long time of trial and error I've tried a diffrent approach of using ListView instead of CustomScrollView, it worked like magic, I set the chiledCount to my LIST.length and all of the sudden there where no errors after that I changed the code to ListView.Builder and changed the body of the Home Scaffold to NestedScrollView and inserted my SliverAppBar into there, probably something is broken indise of the SliverListDelegate

My new code:

      Scaffold(...
      body: NestedScrollView(
      floatHeaderSlivers: true,
      headerSliverBuilder: (BuildContext context, bool innerBoxIsScrolled) {
        return <Widget>[
          SliverAppBar(...),
      ];
      },
      body: HandlyCallsList(),
    ),
  ),

The listView Builder

class _HandlyCallsListState extends State<HandlyCallsList> {


@override
Widget build(BuildContext context) {


final handlyCalls = Provider.of<List<HandlyCall>>(context);

return ListView.builder(
  itemCount: handlyCalls.length,
    itemBuilder: (context, index) {
    return HandlyCallTile(handlyCall: handlyCalls[index],);
    }
);
}
}
Nitai Dan
  • 29
  • 1
  • 6