Skip to content

Possibly undocumented behaviour in ListView.builder #58371

Description

@k-e-l-p

It seems that ListView.builder only builds items until it's itemBuilder callback returns null, ignoring everything else afterwards. In other words, the itemBuilder callback must ALWAYS return a non-null Widget or else it will not display any meaningful data that may come after any uninitialized Widget. Is this intended behaviour? I think it would be better if itemBuilder just carried on until it reached itemCount

Here is a short program to illustrate this behaviour:

import 'package:flutter/material.dart';

void main() {
  runApp(MyApp());
}

class MyApp extends StatelessWidget {
  // This widget is the root of your application.
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter Demo',
      theme: ThemeData(
        primarySwatch: Colors.blue,
        visualDensity: VisualDensity.adaptivePlatformDensity,
      ),
      home: MyHomePage(title: 'Listview bug?'),
    );
  }
}

class MyHomePage extends StatefulWidget {
  MyHomePage({Key key, this.title}) : super(key: key);
  final String title;

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

class _MyHomePageState extends State<MyHomePage> {

  List<String> items = List<String>();


  void addItemToList(){
    setState(() {
      items.add("test");
    });
  }

  void addIgnoredItemToList() {
    setState(() {
      items.add("ignored");
    });
  }

  @override
  Widget build(BuildContext context) {

    return Scaffold(
      appBar: AppBar(
        title: Text(widget.title),
        actions: <Widget>[
          FlatButton(
            child: Text(
              "add item",
            ),
            onPressed: addItemToList,
          ),
          FlatButton(
            child: Text(
              "add ignored item",
            ),
            onPressed: addIgnoredItemToList,
          ),
        ],
      ),
      body: Center(
        child: ListView.builder(
          itemCount: items.length,
          itemBuilder: (context, index) {
            Widget output;

            if (items[index] == "ignored") {
              return output;
            } else {
              output = Text(items[index]);
              return output;
            }
          },
        ),
      ),
      floatingActionButton: FloatingActionButton(
        child: Icon(Icons.clear),
        tooltip: 'Reset',
        onPressed: (){
          setState(() {
            items.clear();
          });
        },
      ),
    );
  }
}

Here is a video demonstrating this behaviour:
https://imgur.com/a/FBupWR5

Flutter --version:

Flutter 1.17.1 • channel stable • https://github.com/flutter/flutter.git
Framework • revision f7a6a7906b (3 weeks ago) • 2020-05-12 18:39:00 -0700
Engine • revision 6bc433c6b6
Tools • Dart 2.8.2

Metadata

Metadata

Assignees

Labels

P2Important issues not at the top of the work listd: api docsIssues with https://api.flutter.dev/found in release: 1.19Found to occur in 1.19frameworkflutter/packages/flutter repository. See also f: labels.has reproducible stepsThe issue has been confirmed reproducible and is ready to work onwaiting for PR to land (fixed)A fix is in flight

Type

No type
No fields configured for issues without a type.

Projects

No projects

Relationships

None yet

Development

No branches or pull requests

Issue actions