Ayman Mashaly
Ayman Mashaly

Reputation: 77

Can't add or update a list

So I'm trying to make a list that contains some widgets and then add a new widget to it when I press a button, but it doesn't seem to be working

This is the code:

class MessagesProvider extends ChangeNotifier{


 List<dynamic> mesgs = [
    new chatBubbleSend(),
    new chatBubbleReceiver(),
    new chatBubbleReceiver()
  ];
  bool loading = true;

  addMesg(){
    mesgs.add(chatBubbleSend());
    print(mesgs.length);
    print(mesgs);
    notifyListeners();
  }
  printMesg(){
    print(mesgs.length);
    print(mesgs);
  }
  removeMesg(){
    mesgs.removeLast();
    print(mesgs.length);
    print(mesgs);
    notifyListeners();
  }
}

and this is what i get when i press the add, remove or print buttons add,remove,print

and this is the list builder code

ChangeNotifierProvider<MessagesProvider>(
                create: (context) => MessagesProvider(),
                child: ChatMessages()
                  ),
class ChatMessages extends StatelessWidget {

  @override
  Widget build(BuildContext context) {
    final mesgs = Provider.of<MessagesProvider>(context, listen: false).mesgs;
    return ListView.builder(
      shrinkWrap: true,
      itemCount: mesgs.length,
      itemBuilder: (context,index)=> mesgs[index],
    );
  }
}

I have looking for a solution for over 8 hours now, and still, I couldn't fix it.

Upvotes: 1

Views: 96

Answers (1)

Ranvir Mohanlal
Ranvir Mohanlal

Reputation: 167

I jumped the gun with my first answer sorry. When trying to recreate I ran into the same frustrating issue - focusing on the the provider being the problem until I realised it's actually the rendering of the updated list that's the issue.

You need to use a list builder to render the updating list in a change notifier consumer in a stateful widget

Full working example below:

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


class WidgetListProvider with ChangeNotifier {

  List<Widget> widgets = [];

  int listLength = 0;

  void addWidget(){
    Widget _widget = Text('Hello');
    widgets.add(_widget);
    listLength = widgets.length;
    print('Added a widget');
    notifyListeners();
  }

  void removeWidget(){
    if (widgets.length > 0) {
      widgets.removeLast();
      listLength = widgets.length;
      print('Removed a widget');
      notifyListeners();
    }
  }

}

class HomePage extends StatefulWidget {
  HomePage({Key key}) : super(key: key);

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

class _HomePageState extends State<HomePage> {

  Widget _appBar (BuildContext context) {
    return AppBar(
      title: Text('My App'),
    );
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: _appBar(context),
      // You need to define widgets that update when a provider changes
      // as children of a consumer of that provider
      body: Consumer<WidgetListProvider>(builder: (context, widgetProvider, child){
        return Container(
          child: Column(
            crossAxisAlignment: CrossAxisAlignment.center,
            mainAxisSize: MainAxisSize.min,
            children: [
              RaisedButton(
                child: Text('Add widget'),
                onPressed: () {
                  widgetProvider.addWidget();
                },
              ),
              RaisedButton(
                child: Text('Remove Widget'),
                onPressed: () {
                  widgetProvider.removeWidget();
                },
              ),
              Row(
                children: [
                  Text('Number of Widgets: '),
                  Text(widgetProvider.listLength.toString()),
                ],
              ),
              Container(
                height: MediaQuery.of(context).size.height*0.6,
                child: ListView.builder(itemCount: widgetProvider.widgets.length, itemBuilder: (BuildContext context, int index){
                  return widgetProvider.widgets[index];
                })
              )
            ],
          ),
        );
      }
      ),
    );
  }
}

void main() {
  runApp(
      ChangeNotifierProvider(
        create: (context) => WidgetListProvider(),
        child: MyApp(),
      )
  );
}

class MyApp extends StatefulWidget {
  @override
  _MyAppState createState() => _MyAppState();
}

class _MyAppState extends State<MyApp> {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'My App',
      home: HomePage(),
    );
  }
}

Upvotes: 1

Related Questions