How NOT To Initialize Lists In Dart: Avoiding Object Sharing And Null Value Surprises

Flutter category image

I never really had trouble with lists in dart. But only until I used null values.

I came across a strange error during development of a game app recently. The game required a 2-dimensional array or list to represent a table structure.

To do this, I chose the data type List<List<MyObject>>. At the beginning, I initialized the structure with null values. Here is the code

Dart
var gameTable = List.filled(_answerRowHeaders.length,
    List.filled(_answerColumnHeaders.length, null));

During testing, I quickly noticed that whenever a cell got assigned a value, the entire column got assigned the same value. How could that happen?

I couldnโ€™t spot the problem in my code although it was a small widget class with less than 300 lines. Eventually I had to ask ChatGPT for help. A major benefit for me is the ability to feed ChatGPT some code and ask it about specific problems. You will most likely get a helpful answers. And it usually works well for me.

Get Free Daily Flutter Content!

Small daily Flutter portions delivered right in your inbox. A title, an abstract, a link, and you decide if you want to dive in!

null can be tricky

After several question rounds, ChatGPT noticed that my initialization code was the problem. List.filled fills a list with the same object passed as the fill argument. In my case, this was the null object of the inner list. I didnโ€™t know that null references could be shared. But to be honest, I also didnโ€™t face this problem before so I never really thought about it.

The correct way for me to initialize lists would have been to use List.generate.

Dart
var gameTable = 
    List.generate(_answerRowHeaders.length, (row) => 
    List.generate(_answerColumnHeaders.length, (col) => null));

With this code, you get different null objects for every entry in your list. And this is what solved my problem.

Conclusion

Beware of the differences between List.filled and List.generate even if you want to use null as a placeholder. This can save you a lot of trouble during debugging!

Related articles