Small knowledge, big challenge! This article is participating in the creation activity of “Essential Tips for Programmers”.
This article has participated in the “Digitalstar Project” and won a creative gift package to challenge the creative incentive money.
A few days ago, XIAO CAI learned about the new state management framework Provider. Provier supports various types of state management methods. Xiao CAI continued to learn the other ones.
ListenableProvider way
1. Data binding
- ListenableProvider({Key key, @required ValueBuilder builder, Disposer dispose, Widget child })
Dispose is used to bind data and listen to it when it is removed from the Widget Tree. Note: The constructor builder cannot be empty;
class MyApp extends StatelessWidget { @override Widget build(BuildContext context) { return ListenableProvider<User>( builder: (_) => User('Flutter', 0), child: MaterialApp( title: 'Flutter Demo', theme: ThemeData(primarySwatch: Colors.blue), home: MyHomePage(title: 'Peovider Demo'))); }}Copy the code
- ListenableProvider.value({Key key, @required T listenable, Widget child })
Use. Value to listen on data. Listenable;
class MyApp extends StatelessWidget { @override Widget build(BuildContext context) { return ListenableProvider<User>.value( listenable: User('Flutter', 0), child: MaterialApp( title: 'Flutter Demo', theme: ThemeData(primarySwatch: Colors.blue), home: MyHomePage(title: 'Peovider Demo'))); }}Copy the code
2. Obtain data
Xiaocai did not mention in his last blog that all data acquisition methods are basically the same and all support two methods.
- The Provider of (context)
class ProviderText extends StatelessWidget { @override Widget build(BuildContext context) { final user = Provider.of<User>(context); return Text('${user.getName}'); }}Copy the code
- Consumer Widget constructor mode
class ProviderText extends StatelessWidget { @override Widget build(BuildContext context) { return Consumer<User>(builder: (context, user, _) { return Text(user.getName); }); }}Copy the code
ValueListenableProvider way
When using ValueListenableProvider, note that the data to be bound must inherit from ValueNotifier, implement its constructor, and update the value operation. Create a Person entity class to operate on.
Class StringBean extends ValueNotifier<String> {StringBean(String value) : super(value); } class Person extends ValueNotifier<User> {Person(User value) : super(value); String get getPersonName => value.name; void setPersonName(String name) { value.name = name; notifyListeners(); }}Copy the code
1. Bind data
- ValueListenableProvider({Key key, @required ValueBuilder<ValueNotifier> builder, UpdateShouldNotify updateShouldNotify, Widget child })
Bind data and listen through the constructor, and the constructor Builder cannot be empty;
class MyApp extends StatelessWidget { @override Widget build(BuildContext context) { return ValueListenableProvider<User>( builder: (_) => Person(User('person', 101)), child: MaterialApp( title: 'Flutter Demo', theme: ThemeData(primarySwatch: Colors.blue), home: MyHomePage(title: 'Peovider Demo'))); }}Copy the code
- ValueListenableProvider.value({Key key, @required ValueListenable valueListenable, UpdateShouldNotify updateShouldNotify, Widget child })
Binding monitoring of data through. Value mode;
class MyApp extends StatelessWidget { @override Widget build(BuildContext context) { return ValueListenableProvider<User>.value( valueListenable: Person(User('person', 101)), child: MaterialApp( title: 'Flutter Demo', theme: ThemeData(primarySwatch: Colors.blue), home: MyHomePage(title: 'Peovider Demo'))); }}Copy the code
2. Obtain data
The method of data acquisition is basically consistent with the above;
class ProviderText extends StatelessWidget { @override Widget build(BuildContext context) { final number = Provider.of<String>(context); final person = Provider.of<User>(context); return Center( child: Column(children: <Widget>[ Text('${number.toString()}==${person.getName}'), Consumer<User>(builder: (context, user, _) { return Text(user.getName); }) ])); }}Copy the code
StreamProvider way
1. The introduction of the Stream
Stream exists in the Dart: Async library and is primarily used to handle asynchronous operations; We used it in ListView when we presented network interface data; StreamController() : StreamController(StreamController) : StreamController(StreamController) : StreamController(StreamController) : StreamController(StreamController) : StreamController(StreamController)) Sink.add () enters data to be processed via StreamController().. Stream Outputs processed data. The entire process needs to be controlled by a StreamController; Specific single stream and multi-stream side dishes will be studied later.
2. Bind data
- StreamProvider({Key key, @required ValueBuilder<StreamController> builder, T initialData, … , Widget child })
Create the StreamController through the builder and bind the data, noting that the bind data needs to be initialized in initialData;
class MyApp extends StatelessWidget { @override Widget build(BuildContext context) { return StreamProvider<Teacher>( builder: (_) => StreamController<Teacher>(), initialData: Teacher('Teacher', 101), child: MaterialApp( title: 'Flutter Demo', theme: ThemeData(primarySwatch: Colors.blue), home: MyHomePage(title: 'Peovider Demo'))); } } class Teacher { var tname; var tage; Teacher(this.tname, this.tage); } Expanded(child: TextField( onChanged: (changed) { teacher.tname = changed; teacher.tage = 150; StreamController<Teacher>().sink.add(teacher); }, controller: _phonecontroller, decoration: InputDecoration(hintText: 'please input id ', suffixIcon: IconButton(icon: Icon(Icons.clear, color: Colors.black45), onPressed: () { _phonecontroller.clear(); }))))Copy the code
- StreamProvider.value({Key key, @required Stream stream, T initialData, … , Widget child })
To bind the StreamController stream with.value, initialize the data in initialData.
class MyApp extends StatelessWidget { @override Widget build(BuildContext context) { return StreamProvider<Teacher>.value( stream: StreamController<Teacher>().stream, initialData: Teacher('Teacher', 101), child: MaterialApp( title: 'Flutter Demo', theme: ThemeData(primarySwatch: Colors.blue), home: MyHomePage(title: 'Peovider Demo'))); }}Copy the code
3. Obtain data
class ProviderText extends StatelessWidget { @override Widget build(BuildContext context) { final teacher = Provider.of<Teacher>(context); return Center( child: Column(children: <Widget>[ Text('${teacher.tname}'), Consumer<Teacher>(builder: (context, teacher, _) { return Text('${teacher.tname}==${teacher.tage}'); }) ])); }}Copy the code
summary
- For ease of understanding, the ChangeNotifierProvider used in the previous section is basically the same as ListenableProvider and ValueListenableProvider.
class ChangeNotifierProvider<T extends ChangeNotifier>
extends ListenableProvider<T> implements SingleChildCloneableWidget {}
class ChangeNotifier implements Listenable {}
class ValueListenableProvider<T>
extends AdaptiveBuilderWidget<ValueListenable<T>, ValueNotifier<T>>
implements SingleChildCloneableWidget {}
class ValueNotifier<T> extends ChangeNotifier implements ValueListenable<T> {}
Copy the code
ChangeNotifierProvider inherits from ListenableProvider and the corresponding ChangeNotifier inherits from ListEnable; It’s a subclass of ListenableProvider; ValueNotifier is derived from ChangeNotifier and is similar to ChangeNotifierProvider.
- When using ChangeNotifierProvider and ValueListenableProvider to bind entity classes, inherit the corresponding ChangeNotifier and ValueNotifier respectively.
class User with ChangeNotifier {}
class Person extends ValueNotifier<User> {}
Copy the code
- No matter which. Value method is used, it is recommended to close the listener in Dispose.
@override
void dispose() {
stream.dispose();
super.dispose();
}
Copy the code
The five methods mentioned in Provier have been tried, and the entity classes of the same class have also been tested. If there are any mistakes, please give more guidance!
Source: Little Monk A Ce