Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Flutter listView builder keeps giving this error: "RangeError (index): Invalid value: Not in range 0..19, inclusive: 20"

I have this news ApI, which gets latest news updates but my listview gives me an error even when i have an item "itemCount" to its length.

i tried "_total.length" on the Itemcount but it gives me an error.. which says "The getter 'length' isn't defined for the class 'int'.

Try importing the library that defines 'length', correcting the name to the name of an existing getter, or defining a getter or field named 'length'".

class _NewsUpdateState extends State<NewsUpdate> {

  List _bottomItems = 
   [
    {"icon": FontAwesomeIcons.fire, "index": 0},
    {"icon": FontAwesomeIcons.moneyBillAlt, "index": 1},
    {"icon": FontAwesomeIcons.bell, "index": 2},
    {"icon": FontAwesomeIcons.futbol, "index": 3},
  ];

  String _apiKey = '46d80623786da4a97847da2b6cd7747';

  int _currentTab = 0;
  String _apiUrl = '';
  int _total = 0;
  List _articles = [];
  bool _loading = true;

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

    changeTab(index: 0);
  }

  void changeTab({int index = 0}) {
    //tab1 is about top-headlines
    //tab2 is about bitcoins
    //tab3 = apple
    //tab4 = techcrunch

    switch (index) {
      case 0:
        _apiUrl =
            'https://newsapi.org/v2/top-headlines?country=za&apiKey=' +
                _apiKey;
        break;
      case 1:
        _apiUrl =
            'https://newsapi.org/v2/top-headlines?country=za&category=business&apiKey=' +
                _apiKey;
        break;
      case 2:
        _apiUrl =
            'https://newsapi.org/v2/top-headlines?country=za&category=entertainment&apiKey=' +
                _apiKey;
        break;
      case 3:
        _apiUrl =
            'https://newsapi.org/v2/top-headlines?country=za&category=sports&apiKey=' +
                _apiKey;
        break;
    }

    print(_apiUrl);

    setState(() {
      _loading = true;
      _total = 0;
      _articles = [];
    });

    http.get(_apiUrl).then((response) {
      var data = json.decode(response.body);
      setState(() {
        _total = data['totalResults'];
        _articles = data['articles'];
        _loading = false;
      });
    });
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text(
          "Latest News",
          style: TextStyle(
              color: Colors.black, fontSize: 25.0, fontWeight: FontWeight.bold),
        ),
        elevation: 5.0,
        backgroundColor: Colors.white,
        centerTitle: true,
      ),
      bottomNavigationBar: _buildBottomNavigation(context),
      body: new SafeArea(child: _buildBody(context)),
    );
  }

  _buildBottomNavigation(BuildContext context) {
    var _items = <BottomNavigationBarItem>[];

    for (var item in _bottomItems) {
      _items.add(new BottomNavigationBarItem(
        icon: new Icon(
          item['icon'],
          color: Colors.black,
        ),
        title: new Text(''),
      ));
    }

    return new BottomAppBar(
      color: Colors.white,
      child: new Row(
        mainAxisAlignment: MainAxisAlignment.spaceAround,
        children: _bottomItems.map((x) {
          return new IconButton(
            icon: new Icon(
              x['icon'],
              color: _currentTab == x['index'] ? Colors.black : Colors.black38,
            ),
            onPressed: () {
              setState(() {
                _currentTab = x['index'];
              });
              changeTab(index: x['index']);
            },
          );
        }).toList(),
      ),
    );
  }

  _buildBody(BuildContext context) {
    if (_loading) {
      return new SpinKitCircle(
        color: Colors.black,
        size: 50.0,
      );
    }

    print(_articles);

    return new ListView.builder(
      itemBuilder: (context, int index) {
        return new Padding(
          padding: new EdgeInsets.symmetric(vertical: 8.0, horizontal: 16.0),
          child: new ListItem(data: _articles[index]),
        );
      },
      itemCount: _total,
    );
  }
}

This should set the actual length of the total result from the api to the itemcount

like image 389
Dilen May Avatar asked Jan 01 '23 23:01

Dilen May


1 Answers

I had the same issue:

you have to also pass the itemCount parameter

child: ListView.builder(
    itemCount: list.length,
    itemBuilder: (context, index) {
        return Text(list[index].description);
    }),
like image 194
luckyhandler Avatar answered Jan 12 '23 06:01

luckyhandler