Search code examples
flutterindexinggetrangedropdown

RangeError (index): Invalid value: Valid value range is empty: 0 (http request)


i'm a beginner in flutter and i have a problem with my http request, when i wanna add in my DropdownButton this http request (that i put in the list called deviceGet) or even print it to see it : i have this error :

RangeError(index) : Invalid value : Valid value range is empty : 0

This is all the error message :

 Exception caught by widgets library ═══════════════════════════════════
The following RangeError was thrown building Builder:
RangeError (index): Invalid value: Valid value range is empty: 0

The relevant error-causing widget was
    MaterialApp 
package:chat/main.dart:180
When the exception was thrown, this was the stack
#0      List.[]  (dart:core-patch/growable_array.dart:149:60)
#1      _MyListScreenState.initState 
package:chat/main.dart:226
#2      StatefulElement._firstBuild 
package:flutter/…/widgets/framework.dart:4428
#3      ComponentElement.mount 
package:flutter/…/widgets/framework.dart:4274
#4      Element.inflateWidget 
package:flutter/…/widgets/framework.dart:3269
...
════════════════════════════════════════════════════════════════════════════════
Reloaded 1 of 591 libraries in 363ms.
flutter: 0

════════ Exception caught by widgets library ═══════════════════════════════════
The following RangeError was thrown building Builder:
RangeError (index): Invalid value: Valid value range is empty: 0

The relevant error-causing widget was
    MaterialApp 
package:chat/main.dart:180
When the exception was thrown, this was the stack
#0      List.[]  (dart:core-patch/growable_array.dart:149:60)
#1      _MyListScreenState.initState 
package:chat/main.dart:225
#2      StatefulElement._firstBuild 
package:flutter/…/widgets/framework.dart:4428
#3      ComponentElement.mount 
package:flutter/…/widgets/framework.dart:4274
#4      Element.inflateWidget 

I don't understand this error because i can see my request if i put in the body

ListView.builder(
        itemCount: deviceGet.length,
        itemBuilder: (context, index) {
        return ListTile(
                title: Text("Num $index " + device[index].commands[0].id));
         title: Text("Num $index " + deviceGet[index].name));

or if i put

Text(deviceGet[0].name)

but with warning

This is my code :

import 'dart:convert';
import 'package:flutter/material.dart';

import 'Get.dart';
import 'Device.dart';
import 'Commands.dart';
import 'deviceData.dart';
void main() => runApp(MyApp());

class MyApp extends StatelessWidget {
  @override
  build(context) {
    return MaterialApp(
      debugShowCheckedModeBanner: false,
      title: 'My App',
      theme: ThemeData(
        primarySwatch: Colors.blue,
      ),
      home: MyListScreen(),
    );
  }
}

class MyListScreen extends StatefulWidget {
  @override
  createState() => _MyListScreenState();
}

class _MyListScreenState extends State {
  //
  List<deviceData> dataDevice = deviceData.getDevicesData();

  List<DropdownMenuItem<deviceData>> listDropDevice;
  deviceData deviceSelection;
  //

  var deviceGet = new List<Device>();

  GetDevice() {
    GET.getDevice().then((response) {
      setState(() {
        Iterable list = json.decode(response.body);
        deviceGet = list.map((model) => Device.fromJson(model)).toList();
      });
    });
  }

  void initState() {
    super.initState();
    GetDevice();

    //print(deviceGet[0].name);

    // add in the dropDown
    for (int i = 0; i < 5;) {
      print(i);
      dataDevice.add(deviceData("Device" + i.toString()));
      dataDevice.add(deviceData(deviceGet[0].name));
      i = i + 1;
    }

    listDropDevice = buildDropdownMenuItems(dataDevice);
    deviceSelection = listDropDevice[0].value;
  }

  List<DropdownMenuItem<deviceData>> buildDropdownMenuItems(List devices) {
    List<DropdownMenuItem<deviceData>> items = List();
    for (deviceData device1 in devices) {
      items.add(
        DropdownMenuItem(
          value: device1,
          child: Text(device1.name),
        ),
      );
    }
    return items;
  }

  onChange(deviceData selectionUtilisateur) {
    setState(() {
      deviceSelection = selectionUtilisateur;
    });
  }

  @override
  build(context) {
    return Scaffold(
        appBar: AppBar(
          title: Text("Device List"),
        ),
        body: Column(children: <Widget>[
          //Text(deviceGet[0].name),
          DropdownButton(
            value: deviceSelection,
            items: listDropDevice,
            onChanged: onChange,
          ),
        ]));
  }
}

Thank you for you help


Solution

  • GetDevice() is asynchronous method so it takes time to get data from json and in the begging deviceGet is empty, so it gives error of range.

    you can make GetDevice() method asynchronous using await and async* and while calling that method use .then method and then access values.

    also, make sure that you are getting data in GetDevice metod.