Created
March 27, 2025 20:28
-
-
Save prof3ssorSt3v3/4aab95459ff58a00957ca9fb227adbc9 to your computer and use it in GitHub Desktop.
Flutter example of a change notifier
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import 'package:flutter/material.dart'; | |
import 'package:provider/provider.dart'; | |
//add provider: to the dependencies in pubspec.yaml | |
//update your formatter in analysis_options.yaml | |
// The provider file to be imported in files that need it | |
class NameProvider extends ChangeNotifier { | |
List<String> _names = ['Bob', 'Louise']; | |
//similar in concept to a State variable but it will be | |
//used and managed from inside other widgets in the tree | |
List<String> get names => _names; | |
void addName(String name) { | |
//be sure to validate the new data | |
_names.add(name); | |
//Call notifyListeners() whenever the value changes | |
notifyListeners(); | |
} | |
void removeName(String name) { | |
_names.remove(name); | |
//Call notifyListeners() when the value changes | |
notifyListeners(); | |
} | |
} | |
//main.dart import the provider package AND our custom provider | |
void main() { | |
runApp( | |
ChangeNotifierProvider( | |
create: (context) => NameProvider(), | |
child: MyApp(), | |
), | |
); | |
} | |
class MyApp extends StatelessWidget { | |
const MyApp({super.key}); | |
@override | |
Widget build(BuildContext context) { | |
return MaterialApp( | |
debugShowCheckedModeBanner: false, | |
home: HomePage(), | |
); | |
} | |
} | |
// the page using the Provider through a consumer | |
//import both the provider package and the custom provider files | |
class HomePage extends StatefulWidget { | |
const HomePage({super.key}); | |
@override | |
State<HomePage> createState() => _HomePageState(); | |
} | |
class _HomePageState extends State<HomePage> { | |
final TextEditingController _nameController = | |
TextEditingController(); | |
@override | |
void dispose() { | |
_nameController.dispose(); | |
super.dispose(); | |
} | |
@override | |
Widget build(BuildContext context) { | |
final nameListProvider = Provider.of<NameProvider>(context); | |
return Scaffold( | |
appBar: AppBar(title: Text('Provider Example')), | |
body: Column( | |
children: <Widget>[ | |
Padding( | |
padding: const EdgeInsets.all(8.0), | |
child: Row( | |
children: <Widget>[ | |
Expanded( | |
child: TextField( | |
controller: _nameController, | |
decoration: InputDecoration( | |
labelText: 'Enter Name', | |
), | |
), | |
), | |
SizedBox(width: 8), | |
ElevatedButton( | |
onPressed: () { | |
final name = _nameController.text.trim(); | |
if (name.isNotEmpty) { | |
nameListProvider.addName(name); | |
//Provider.of<NameProvider>(context) | |
_nameController.clear(); | |
} | |
}, | |
child: Text('Add'), | |
), | |
], | |
), | |
), | |
Expanded( | |
child: Consumer<NameProvider>( | |
builder: (context, provider, child) { | |
//provider == Provider.of<NameProvider>(context) | |
return ListView.builder( | |
itemCount: provider.names.length, | |
itemBuilder: (context, index) { | |
final name = provider.names[index]; | |
return ListTile( | |
title: Text(name), | |
trailing: OutlinedButton.icon( | |
icon: Icon(Icons.delete), | |
label: child!, | |
onPressed: () { | |
provider.removeName(name); | |
}, | |
), | |
); | |
}, | |
); | |
}, | |
child: Text('Delete'), | |
//becomes the child param in builder: (context, provider, child) | |
), | |
), | |
], | |
), | |
); | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment