Iterator current is null, but why?

Viewed 385

What I want to obtain is a method of generating widgets through a predefined step sequence: widget1 -> widget 2-> widget3 -> done. And I thought of making a list of the widgets, and the way to "advance" to the next widget, would be to call moveNext() on the iterator. But clearly I'm missing something:

According to the docs here, if moveNext() is called on the iterator and it returned true, then afterwards the iterator.current will not be null. When printing print(hasAdvanced) it returns true, so iterator.current should not be null. But it is. Why is it null? What am I missing?

import 'package:flutter/material.dart';

class CreatePageWidget extends StatefulWidget {
  @override
  _CreatePageState createState() => _CreatePageState();
}

class _CreatePageState extends State<CreatePageWidget> {
  List<Widget> sequence = [Text("one"), Text("two")];

  @override
  void initState() {
    super.initState();

    bool hasAdvanced = sequence.iterator.moveNext();
    print(hasAdvanced);
    print(sequence.iterator.current);
  }

  @override
  Widget build(BuildContext context) => sequence.iterator.current;
}
1 Answers

You have:

 bool hasAdvanced = sequence.iterator.moveNext();
 print(hasAdvanced);
 print(sequence.iterator.current);

You call sequence.iterator twice, but Iterable.iterator always returns a new iterator. From the documentation:

Returns a new Iterator that allows iterating the elements of this Iterable.

...

Each time iterator is read, it returns a new iterator, which can be used to iterate through all the elements again. The iterators of the same iterable can be stepped through independently, ....

So even though you initially advanced the Iterator successfully, you then retrieve the current value from a different Iterator, which hasn't been advanced and therefore is still null. You can fix this by simply keeping a reference to a single Iterator:

var iterator = sequence.iterator;
bool hasAdvanced = iterator.moveNext();
print(hasAdvanced);
print(iterator.current);

(Personally I think it is confusing and bad style for a property/getter to return new instances and that this would have been more obvious as an explicit function call. Changing the API now probably would not be worth the trouble, though.)

Related