Flutter does not display stateful children Widget in ListView

263

Your CRD widget is a StatefulWidget and the state will be reused when rebuilding since the type of the widget is the same an you did not give it a key.

To solve your issue there are a few possibilities:

  1. Add a key to all the items in the list
  2. Implement the didUpdateWidget method in the state of your widget
  3. Use a statelesswidget and do the string concatination in the build method
Share:
263
Knoll Alexander
Author by

Knoll Alexander

Updated on December 25, 2022

Comments

  • Knoll Alexander
    Knoll Alexander over 1 year

    As in the titel, I have a problem with ListView and I hope you can help me out.

    I am using a basic ListView to build "Card Widgets" (with their own state). The ListView uses a List of Ids, which are used to build those "Card Widgets"

    The problem: Any time I remove a card from the list by deleting an Id the ListView always removes the top most Child Widget. My backend deletes the right things, becouse after I restart the app so that the page gets populated anew, the deleted card is actually deleted and the one the removed by the ListView is visible again. It seems like ListView does not redraw it's children. Any Idea what is going on?

    I created basic DartPad code to illustrate the problem

    import 'package:flutter/material.dart';
    
    void main() => runApp(MyApp());
    
    class MyApp extends StatelessWidget {
      @override
      Widget build(BuildContext context) {
        return MaterialApp(
          title: 'Flutter Demo',
          debugShowCheckedModeBanner: false,
          theme: ThemeData(
            primarySwatch: Colors.blue,
          ),
          home: MyHomePage(title: 'Flutter Demo Home Page'),
        );
      }
    }
    
    class MyHomePage extends StatefulWidget {
      MyHomePage({Key key, this.title}) : super(key: key);
    
      final String title;
      @override
      _MyHomePageState createState() => _MyHomePageState();
    }
    
    class _MyHomePageState extends State<MyHomePage> {
      int _counter = 0;
      List<String> dd = new List<String>();
      
      @override
      void initState() {
        super.initState();
        dd.add('A');
        dd.add('B');
        dd.add('C');
        dd.add('D');
      }
    
      
    
      void _incrementCounter() {
        setState(() {
          _counter++;
          dd.insert(1, 'Q');
        });
      }
    
      @override
      Widget build(BuildContext context) {
        return Scaffold(
          appBar: AppBar(
            title: Text(widget.title + _counter.toString()),
          ),
          body: ListView.builder(
            addAutomaticKeepAlives: false,
            itemBuilder: (context, index) {
              print('calling: $index :' + _counter.toString() + ' -> ' + dd[index] );
              return new CRD(title: dd[index]);
            },
            itemCount: dd.length
          ),
          /*
          ListView(
            children: dd.map((str) {
              return CRD(title: str);
            }).toList()
          ),
          */
          floatingActionButton: FloatingActionButton(
            onPressed: _incrementCounter,
            tooltip: 'Increment',
            child: Icon(Icons.add),
          ),
        );
      }
    }
    
    class CRD extends StatefulWidget {
      
      CRD({Key key, this.title}) : super(key: key);
    
      final String title;
      @override
      _CRD createState() => _CRD();
    }
    
    class _CRD extends State<CRD> {
    
      String _val;
      
      @override
      void initState() {
        super.initState();
        _val = widget.title + ' ' + widget.title;
      }
    
      @override
      Widget build(BuildContext context) {
        return Text(_val);
      }
    }
    

    So after clicking once on the Add button the list content is [A,Q,B,C,D] but the app displays [A,B,C,D,D]. Whats going on here? Am i missing something?

  • Knoll Alexander
    Knoll Alexander over 3 years
    Ok, so basically I populate my widget state within the 'didUpdateWidget' based upon my widget instance? I need to do that because the underlying state is reused and not created again. Is that right? Implementing 'didUpdateWidget' gave the results I expected! Thanks!
  • Pieter van Loon
    Pieter van Loon over 3 years
    Well partially yes, didUpdateWidgetbis only called if it is rebuilt so you also need to do it in initState still
  • Knoll Alexander
    Knoll Alexander over 3 years
    Okay thanks alot! Adding a key seems the easiest for what I want to do. Have a nice day :)