Search code examples
flutterprovider-model

Why button needs to be pressed twice for state update in flutter using provider?


I am fairly new to flutter just been a few days.

I am trying my hands on provider pattern, and find it easy to use and understand. However, after implementing i found the button is needed to press twice for the update of state.

I have checked everywhere, like double function call and nothing seems wrong. Here is the code.

    class CounterPage extends StatelessWidget {

  final changeName = TextEditingController();
  final changeNumber = TextEditingController();

  @override
  Widget build(BuildContext context) {
    final CounterBloc counterBloc = Provider.of<CounterBloc>(context);
    return Scaffold(
      appBar: 
      AppBar(
        title: Text(counterBloc.name.toString()),
      ),
      body: Container(
        child: Center(
          child: Column(
            children: <Widget>[
              Text(
                counterBloc.counter.toString(),
                style: TextStyle(fontSize: 62.0),
              ),
              TextField(
                controller: changeName,
              ),
                TextField(
                controller: changeNumber,
              ),
              IncrementButton( changeNumber.text, changeName.text),
            ],
          ),
        ),
      ),
    );
  }
}

The nomenclature is wrong, the use of the increment button is to, just pass two string and set to some places in UI using provider.

This is what my increment button looks like, SImple nothing fancy

   class IncrementButton extends StatelessWidget{

  final String name;
  final String number;
  IncrementButton(this.name, this.number);
  @override
  Widget build(BuildContext context) {
    final CounterBloc counterBloc = Provider.of<CounterBloc>(context);
    return FlatButton.icon(
      icon: Icon(Icons.add),
      label: Text("Add"),
      onPressed: ()=>counterBloc.nameAndCounter(name,number),
    );
  }

}

And this is what counterBloc looks like

   import 'package:flutter/material.dart';

class CounterBloc extends ChangeNotifier{

  String _counter = "10";
  String _name ="Alphhit";

  String get counter => _counter;
  String get name => _name;
   nameAndCounter( String name, String digit){
    _name =  name;
    _counter = digit;

    notifyListeners();
  }
}

The state gets updated and reflected only after pressing the button twice? Can someone please tell what I am doing wrong ?


Solution

  • When you call the IncrementButton( changeNumber.text, changeName.text,), it will start with the previous values so you must update it when you add a new text. You can use onChanged: (_){setState(() {});

    Column( children: <Widget>[
                  Text(
                    counterBloc.counter,
                    style: TextStyle(fontSize: 62.0),
                  ),
                  TextField(
                    controller: changeName,
                    onChanged: (_){
                      setState(() {
                      });
                    },
                  ),
                    TextField(
                    controller: changeNumber,
                    onChanged: (_){
                      setState(() {
                      });
                    },
                  ),
                  IncrementButton( changeNumber.text, changeName.text,),
                ],
              ),
    

    Or send the function to the button

        class CounterPage extends StatelessWidget {
    
      final changeName = TextEditingController();
      final changeNumber = TextEditingController();
      final changeName = TextEditingController();
    
      final changeNumber = TextEditingController();
       _updateData() {
         Provider.of<CounterBloc>(context).nameAndCounter(changeNumber.text, changeName.text);
      }
    
      @override
      Widget build(BuildContext context) {
        CounterBloc counterBloc = Provider.of<CounterBloc>(context);
        print(counterBloc.name);
        return Scaffold(
          appBar: AppBar(
            title: Text(counterBloc.name),
          ),
          body: Container(
            child: Center(
              child: Column(
                children: <Widget>[
                  Text(
                    counterBloc.counter,
                    style: TextStyle(fontSize: 62.0),
                  ),
                  TextField(
                    controller: changeName,
    
                  ),
                  TextField(
                    controller: changeNumber,
    
                  ),
                  IncrementButton(_updateData),
                ],
              ),
            ),
          ),
        );
      }
    }
    
    class IncrementButton extends StatelessWidget {
      final Function updateData;
    
      IncrementButton(this.updateData);
      @override
      Widget build(BuildContext context) {
        return FlatButton.icon(
          icon: Icon(Icons.add),
          label: Text("Add"),
          onPressed: updateData,
        );
      }
    }