Append items dynamically to ListView

19,387

Calling setState is the correct way of triggering an UI update.

From the docs:

Calling setState notifies the framework that the internal state of this object has changed in a way that might impact the user interface in this subtree, which causes the framework to schedule a build for this State object.

If you just change the state directly without calling setState, the framework might not schedule a build and the user interface for this subtree might not be updated to reflect the new state.

Here is a small example of a ListView with a Button that appends items to it.

import 'package:flutter/material.dart';

void main() => runApp(new MaterialApp(home: MyList()));

class MyList extends StatefulWidget {
  @override
  _MyListState createState() => _MyListState();
}

class _MyListState extends State<MyList> {
  int value = 2;

  _addItem() {
    setState(() {
      value = value + 1;
    });
  }

  @override
  Widget build(BuildContext context) {
    return new Scaffold(
      appBar: AppBar(
        title: Text("MyApp"),
      ),
      body: ListView.builder(
          itemCount: this.value,
          itemBuilder: (context, index) => this._buildRow(index)),
      floatingActionButton: FloatingActionButton(
        onPressed: _addItem,
        child: Icon(Icons.add),
      ),
    );
  }

  _buildRow(int index) {
    return Text("Item " + index.toString());
  }
}
Share:
19,387
Daniel Stephens
Author by

Daniel Stephens

Updated on June 12, 2022

Comments

  • Daniel Stephens
    Daniel Stephens about 2 years

    I am new to Dart and Flutter and try to append a new item to my ListView. I created a button that increments this.value but nothing happens. Am I missing an update call on the UI and is this even the correct approach? Since I return the value of ListView.builder directly to the caller of build I am not sure how to get the list to add more items. Thanks a lot!

    class MyList extends State<MyList> {
    
    ... 
    int value = 2;
    
    @override
    Widget build(BuildContext context) {
    return ListView.builder(
        itemCount: this.value,
        itemBuilder: (context, index) => this._buildRow(index)
    );
    

    TL;DR: Is calling setState the correct way to trigger an UI update?

  • Daniel Stephens
    Daniel Stephens almost 6 years
    Awesome! Thanks a lot for the example! Works like a charm
  • user2134488
    user2134488 over 2 years
    But what if the floatingActionButton would be outside of the _MyListState class?
  • aceBox
    aceBox over 2 years
    This would also rebuild the rows already added, no? Any way to avoid that and only build fresh rows in the ListView, to keep it lightweight?