Flutter: In stateless widget I get "The instance member 'xy' can't be accessed in an initializer." when using length on array xy

950

Solution 1

It's related to the order of things happening when you call the constructor. Both parameters and noOfButtons are fields and one is not necessarily assigned before the other. If you want to use fields in other final fields, you have to do it in the initializer list. https://dart.dev/guides/language/language-tour#initializer-list.

So, this should work:

class createParameterButtons extends StatelessWidget {
  final List<Parameter> parameters;
  final String unnknown;
  createParameterButtons({this.parameters, this.unnknown}) : noOfButtons = parameters.length, loopEnd = loopEnd = (noOfButtons / 7).truncate() + (noOfButtons % 7 < 5 ? 1 : 2);
  final noOfButtons;
  final loopEnd;
  @override
  Widget build(BuildContext context) {
    return Column(children: <Widget>[
      Text("a"),
    ],
    ),
}  }

Solution 2

You could just make your variables local variables to your build method.

If for some reason they need to be class members, you need to initialize them in the constructor, that is called an initializer list:

class createParameterButtons extends StatelessWidget {
  final List<Parameter> parameters;
  final String unknown;
  final int noOfButtons;
  final int loopEnd;

  createParameterButtons({this.parameters, this.unknown})
  : noOfButtons = parameters.length,
    loopEnd = (parameters.length / 7).truncate() + (parameters.length % 7 < 5 ? 1 : 2);

Solution 3

final loopEnd = ...

create a class property. It is executed before the object is initialized, so you can't access this (or this.noOfButtons in this case) since it might not be initialized yet. You can initialize the loopEnd inside the build method instead, then the object is fully created.

Btw, according to convention you should name the class in UpperCamelCase, so class CreateParameterButtons instead of class createParameterButtons

Share:
950
w461
Author by

w461

Programmed C long time ago, did some minor VBA in between and currently I am trying to create some basic home schooling apps in flutter and/or swift - just in case...

Updated on December 23, 2022

Comments

  • w461
    w461 over 1 year

    This is now the 2nd spot in my code where I face this issue (1st one still pending, because I thought it would be caused by something else)

    In a child stateless class I create a final based on a parameter being passed to this class. This throws The instance member 'parameters' can't be accessed in an initializer.

    class createParameterButtons extends StatelessWidget {
      final List<Parameter> parameters;
      final String unnknown;
      createParameterButtons({this.parameters, this.unnknown});
      final noOfButtons = parameters.length;
      final loopEnd = (noOfButtons / 7).truncate() + (noOfButtons % 7 < 5 ? 1 : 2);
      @override
      Widget build(BuildContext context) {
        return Column(children: <Widget>[
          Text("a"),
        ],
        ),
    }  }
    

    In guess I have figured out that I cannot use variables in a stateless widget (though I could have one in a for loop). But why doesn't a final based on a parameter work? Is this a general design or am I doing anything stupid?

    I know, I can send the array length as another parameter as a workaround. But I would like to understand the problem.

    • w461
      w461 almost 4 years
      especially as the problem continues with "loopEnd=" after passing the number of elements to the class...
  • w461
    w461 almost 4 years
    Ah, now I understand the notation of classname(...) : which I have already noticed before. I am accepting this answer because it is timely the 1st explaining the reason and providing the solution with the initializer list (which I find a bit cleaner that a declaration in the build method). THANKS TO ALL OF YOU!
  • w461
    w461 almost 4 years
    "you should name the class in UpperCamelCase," Thanks. One typo propagated by copy paste :-) Others are UpperC...