'onTap in GestureDetector is taking a value less, but Text is taking correct, both used in the same loop

In the following code, Text(subjects[address]) is printing the correct value, but GestureDetector( onTap: is taking the same value for the whole Row, and incrementing the values of subject and address directly by 2 and 6 respectively, at exit from inner loop,

Column(
  children: [
    for (int i = 0, address = 0, subject = 0; i < 3; i++)
      Row(
        children: [
          for (int j = 0; j < 2; address += 3, subject++, j++)
            GestureDetector(
              child: Text(subjects[address]),
              onTap: () {.........},
            ),
        ],
      ),
  ],
),

the code prints: enter image description here,

so when i tap 'Second', onTap should execute the code of 'Second', which is subject('1' at Second), but it is taking '2', for both First and Second, and '4' for Third, and Fourth, and '6' for Fifth and Sixth, and as subject is being incremented by 2, address is being incremented by 6,

Thanking you...



Solution 1:[1]

Nearest Solution

GridView.count, with physics: const NeverScrollableScrollPhysics(), and shrinkWrap: true, and crossAxisCount: 2.

Reason (behind code failure)

The correct (intended) behavior is shown by the outer loop ( inside Column( children: [..],),) as given in the official language-tour, While the behavior shown by the inner loop ( inside Row( children: [..],),, is incorrect and wrong, possibly a bug,

Official Quotation

Code:

var callbacks = [];
for (var i = 0; i < 3; i++) {
  callbacks.add(() => print(i));
}
callbacks.forEach((c) => c());

Correct (intended) Output:

0
1
2

Incorrect (wrong) Output:

2
2
2

Solution 2:[2]

While rendering the UI, it takes the current value of "subject" variable, so the UI part is correct.

OnTap does not work correctly because the value of subject variables gets changed after each iteration in the for loop, so when the ontap is called it just takes the last value of "subject" variable which is the 2,4,6 that you get for each ROW.

Solution:

  1. Hard Code: If you are sure there are only 6 buttons on the screen then you could just hard code it.
  2. Use ListView Builder: If the for loops condition is not constant then better use listview.builder (for row) within another listview.builder (for column).

The solution I have given is very short and abstract. Do comment if you need further explanation.

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1
Solution 2 Nagulan S