I'm trying to read data from some mock endpoint. [Mock endpoint I'm invoking (HTTP GET) is here](https://stoplight.io/mocks/ragingtortoise/test/82311857/configuration/tools/optics).

Essentially, the JSON structure is `result` > `toolList[]` > `category` > `tools[]`. I'd like to display these items on my page in such a way that the category name is displayed first, then items belonging to that category under it. I am trying to achieve this with ListView.builder but I somehow managed to get some sort of infinite loop and the items keep getting populated until my device freezes.

What I'm trying to achieve:

* Category Title
	+ Item 1
	+ Item 2
* Category Title 2
	+ Item 1
	+ Item 2
	+ Itme 3

And finally the Widget:

```
class OpticsSelectorWidget extends StatefulWidget {
  const OpticsSelectorWidget({Key key}) : super(key: key);

  @override
  _OpticsSelector createState() => _OpticsSelector();
}

class _OpticsSelector extends State<OpticsSelectorWidget> {
  PageController pageViewController;
  final scaffoldKey = GlobalKey<ScaffoldState>();

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

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      backgroundColor: Colors.white,
      appBar: StandardAppbarWidget(appBarTitle: "some title"),
      body: SizedBox(
        child: FutureBuilder<ApiCallResponse>(
          future: ConfigurationController.getOpticsTools2(),
          builder: (context, snapshot) {
            if (!snapshot.hasData) {
              return Center(
                child: SizedBox(
                  width: 50,
                  height: 50,
                  child: CircularProgressIndicator(
                    color: Colors.red,
                  ),
                ),
              );
            }

            final gridViewGetToolsOpticsResponse = snapshot.data;

            var toolCategories = getJsonField(
              gridViewGetToolsOpticsResponse.jsonBody,
              r'''$.result.toolList''',
            ).toList();

            return Builder(
              builder: (context) {
                return ListView.builder(itemBuilder: (context, itemIndex) {
                  final widgets = <Widget>[];

                  for (int i = 0; i < toolCategories.length; i++) {
                    var currentToolCategory = getJsonField(
                      toolCategories[i],
                      r'''$.category''',
                    );

                    widgets.add(Text(
                      currentToolCategory,
                      style: Colors.white,
                    ));

                    var toolListInCategory = getJsonField(
                      toolCategories[itemIndex],
                      r'''$.tools''',
                    );

                    for (int j = 0; j < toolListInCategory.length - 1; j++) {
                      var toolDisplayName = getJsonField(
                        toolListInCategory[j],
                        r'''$.displayName''',
                      );

                      widgets.add(Text(toolDisplayName));
                    }
                  }
                  return SingleChildScrollView(
                      child: Column(
                    children: widgets,
                  ));
                });
              },
            );
          },
        ),
      ),
    );
  }
}

```

I'm especially confused about the itemIndex expression. That number I thought would be the item count that I receive from my API call, but I guess I'm mixing something badly.

If it helps, here's the bit where I'm making the API call. But feel free to just grab the JSON your way ([from mock response](https://stoplight.io/mocks/ragingtortoise/test/82311857/configuration/tools/optics))

```
static Future<ApiCallResponse> getOpticsTools2() async {    
    HttpOverrides.global = new MyHttpOverrides();
    var client = http.Client();
    try {
      var response = await client.get(Uri.https('stoplight.io'
      , "mocks/ragingtortoise/test/82311857/configuration/tools/optics"));

      return createResponse(response, true);
    } finally {
      client.close();
    }
}

static ApiCallResponse createResponse(http.Response response, bool returnBody) {
    var jsonBody;
    try {
      jsonBody = returnBody ? json.decode(response.body) : null;
    } catch (_) {}

    return ApiCallResponse(jsonBody, response.statusCode);
}

```

And the return type, which is `ApiCallResponse`:

```
class ApiCallResponse {
  const ApiCallResponse(this.jsonBody, this.statusCode);
  final dynamic jsonBody;
  final int statusCode;
  bool get succeeded => statusCode >= 200 && statusCode < 300;
}

```

Finally adding the screen recording of what's happening, if it helps.

[![enter image description here](https://i.stack.imgur.com/4J358.gif)](https://i.stack.imgur.com/4J358.gif)