"<p>In this video, we are going to see how to how to save form data using the Provider plugin in Flutter.</p> <p><strong>Provider Package:</strong></p> <p>The provider package is a wrapper around the InheritedWidgets library that makes it simpler to use. It provides a state management technique for managing data around your app.</p> <p>Some of the basic classes available in the provider package are :</p> <p><strong>ChangeNotifierProvider</strong><T extends ChangeNotifier>: It listens to a ChangeNotifier that’s extended by the model class, exposes it to its children and descendants, and rebuilds its dependencies every time the notifyListeners method is called.</p> <p><strong>Consumer<T>: </strong>It can obtain a value from a provider when we don't have a BuildContext that is a descendant of this provider, and then we can not use Provider.of.</p> <p><strong>InheritedProvider<T>:</strong> The InheritedProvider provides us a general implementation of the <strong>InheritedWidget</strong>.</p> <p><strong>MultiProvider:</strong> is a provider that is used to provide us with more than one class at the same time.</p> <p>In this video we added a method in our Task Model,this method will allow us to add new Tasks in <kbd>_todoTasks</kbd> :<code> </code></p> <pre> <code>// taskModel.dart void add(Task _task){ _todoTasks.add(_task); notifyListeners(); }</code></pre> <p>The following snippet of code is our Add Task View:</p> <pre> <code>// AddTasksView.dart return Consumer<TaskModel>( builder: (context, model, child) { return Scaffold( appBar: AppBar( title: Text("Add new Task"), ), body: SingleChildScrollView( child: Form( key: _formKey, child: Padding( padding: const EdgeInsets.symmetric(horizontal: 8.0), child: Column(children: <Widget>[ TableCalendar( calendarFormat: CalendarFormat.week, firstDay: DateTime.utc(2022, 1, 1), lastDay: DateTime.utc(2050, 12, 31), focusedDay: _focusedDay, selectedDayPredicate: (day) { return isSameDay(_selectedDay, day); }, onDaySelected: (selectedDay, focusedDay) { setState(() { _selectedDay = selectedDay; _focusedDay = focusedDay; // update `_focusedDay` here as well }); }, onPageChanged: (focusedDay) { _focusedDay = focusedDay; }, calendarBuilders: CalendarBuilders( markerBuilder: (context, datetime, events) { return Container( width: 20, height: 15, decoration: BoxDecoration( color: globals.primaries[1], borderRadius: BorderRadius.circular(4.0) ), ); }, selectedBuilder: (context, _datetime, focusedDay) { return Container( decoration: BoxDecoration( color: Colors.blue, borderRadius: BorderRadius.circular(4.0) ), margin: EdgeInsets.symmetric( vertical: 4.0, horizontal: 10.0), child: Center( child: Text(_datetime.day.toString(), style: TextStyle(color: Colors.white),), ), ); } ), ), Padding( padding: const EdgeInsets.only(top: 12.0), child: TextFormField( controller: _titleController, maxLength: 100, decoration: InputDecoration( hintText: "Enter Task Title", focusedBorder: OutlineInputBorder( borderRadius: BorderRadius.circular(5.0), borderSide: BorderSide( color: Colors.blue, width: 2.0 ) ), enabledBorder: OutlineInputBorder( borderRadius: BorderRadius.circular(5.0), borderSide: BorderSide( color: Colors.blue, width: 2.0 ) ), errorBorder: OutlineInputBorder( borderRadius: BorderRadius.circular(5.0), borderSide: BorderSide( color: Colors.red, width: 2.0 ) ), focusedErrorBorder: OutlineInputBorder( borderRadius: BorderRadius.circular(5.0), borderSide: BorderSide( color: Colors.red, width: 2.0 ) ), ), validator: (value) { if (value == null || value.isEmpty) { return 'Please enter some text'; } return null; }, Padding( padding: const EdgeInsets.only(top: 8.0), child: TextFormField( controller: _descriptionController, maxLength: 500, minLines: 3, maxLines: 6, decoration: InputDecoration( hintText: "Enter Task Description (optional)", focusedBorder: OutlineInputBorder( borderRadius: BorderRadius.circular(5.0), borderSide: BorderSide( color: Colors.blue, width: 2.0 ) ), enabledBorder: OutlineInputBorder( borderRadius: BorderRadius.circular(5.0), borderSide: BorderSide( color: Colors.blue, width: 2.0 ) ), errorBorder: OutlineInputBorder( borderRadius: BorderRadius.circular(5.0), borderSide: BorderSide( color: Colors.red, width: 2.0 ) ), focusedErrorBorder: OutlineInputBorder( borderRadius: BorderRadius.circular(5.0), borderSide: BorderSide( color: Colors.red, width: 2.0 ) ), ), ), ), ]), ), ), ), floatingActionButton: FloatingActionButton( child: Icon(Icons.done), onPressed: () { if (_formKey.currentState!.validate()) { Task _newTask = Task( _titleController.text, false, _descriptionController.text, _focusedDay); model.add(_newTask); ScaffoldMessenger.of(context).showSnackBar( const SnackBar(content: Text('Task saved...')), ); Navigator.pushReplacementNamed(context, 'listTasks'); } }, ), );} ); }</code></pre> <p>Dispose method is called<strong> when our widget is removed from the tree permanently</strong>. The framework calls dispose method when the state of the widget or the object will never build again.So the framework calls dispose, and the state  of our Widget is considered unmounted and the value of the mounted property is false.</p> <pre> <code>@override void dispose() { _titleController.dispose(); _descriptionController.dispose(); super.dispose(); } }</code></pre>"