github:
https://github.com/rrousselGit/provider
demo:
https://github.com/rrousselGit/provider/tree/master/example
步骤:
1、 初始化
在pubspec.yaml中添加Provider的依赖。
provider: 3.2.0
2、 创建Model
class Counter with ChangeNotifier {
int _count = 0;
int get count => _count;
void increment() {
_count++;
notifyListeners();
}
}
3、使用Provider,将Provider放入顶层
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MultiProvider(
providers: [
ChangeNotifierProvider(create: (_) => Counter()),
],
child: Consumer<Counter>(
builder: (context, counter, _) {
return MaterialApp(
supportedLocales: const [Locale('en')],
localizationsDelegates: [
DefaultMaterialLocalizations.delegate,
DefaultWidgetsLocalizations.delegate,
_ExampleLocalizationsDelegate(counter.count),
],
home: const MyHomePage(),
);
},
),
);
}
}
ChangeNotifierProvider继承ListenableProvider
/// Listens to a [ChangeNotifier], expose it to its descendants and rebuilds
/// dependents whenever the [ChangeNotifier.notifyListeners] is called.
class ChangeNotifierProvider<T extends ChangeNotifier>
extends ListenableProvider<T> implements SingleChildCloneableWidget {
static void _disposer(BuildContext context, ChangeNotifier notifier) =>
notifier?.dispose();
/// Creates a [ChangeNotifier] using `create` and automatically
/// dispose it when [ChangeNotifierProvider] is removed from the widget tree.
///
/// `create` must not be `null`.
ChangeNotifierProvider({
Key key,
@required ValueBuilder<T> create,
@Deprecated('will be removed in 4.0.0, use create instead')
ValueBuilder<T> builder,
Widget child,
}) : super(
key: key,
create:
// ignore: deprecated_member_use_from_same_package
create ?? builder,
dispose: _disposer,
child: child,
);
/// Provides an existing [ChangeNotifier].
ChangeNotifierProvider.value({
Key key,
@required T value,
Widget child,
}) : super.value(key: key, value: value, child: child);
}
ListenableProvider构造中ListenableDelegateMixin初始化
/// `create` must not be `null`.
ListenableProvider({
Key key,
@required ValueBuilder<T> create,
@Deprecated('Will be removed as part of 4.0.0, use create instead')
ValueBuilder<T> builder,
Disposer<T> dispose,
Widget child,
}) : this._(
key: key,
delegate:
// ignore: deprecated_member_use_from_same_package
_BuilderListenableDelegate(create ?? builder, dispose: dispose),
child: child,
);
_ListenableDelegateMixin 初始化监听
@override
void initDelegate() {
super.initDelegate();
if (value != null) startListening(value);
}
@override
void didUpdateDelegate(StateDelegate old) {
super.didUpdateDelegate(old);
final delegate = old as _ListenableDelegateMixin<T>;
_removeListener = delegate._removeListener;
updateShouldNotify = delegate.updateShouldNotify;
}
void startListening(T listenable, {bool rebuild = false}) {
/// The number of time [Listenable] called its listeners.
///
/// It is used to differentiate external rebuilds from rebuilds caused by
/// the listenable emitting an event. This allows
/// [InheritedWidget.updateShouldNotify] to return true only in the latter
/// scenario.
var buildCount = 0;
final setState = this.setState;
final listener = () => setState(() => buildCount++);
var capturedBuildCount = buildCount;
// purposefully desynchronize buildCount and capturedBuildCount
// after an update to ensure that the first updateShouldNotify returns true
if (rebuild) capturedBuildCount--;
updateShouldNotify = (_, __) {
final res = buildCount != capturedBuildCount;
capturedBuildCount = buildCount;
return res;
};
listenable.addListener(listener);
_removeListener = () {
listenable.removeListener(listener);
_removeListener = null;
updateShouldNotify = null;
};
}
ListenableProvider build 函数返回InheritedProvider,InheritedProvider继承InheritedWidget
@override
Widget build(BuildContext context) {
final delegate = this.delegate as _ListenableDelegateMixin<T>;
return InheritedProvider<T>(
value: delegate.value,
updateShouldNotify: delegate.updateShouldNotify,
child: child,
);
}
/// A generic implementation of an [InheritedWidget].
///
/// Any descendant of this widget can obtain `value` using [Provider.of].
///
/// Do not use this class directly unless you are creating a custom "Provider".
/// Instead use [Provider] class, which wraps [InheritedProvider].
class InheritedProvider<T> extends InheritedWidget {
/// Allow customizing [updateShouldNotify].
const InheritedProvider({
Key key,
@required T value,
UpdateShouldNotify<T> updateShouldNotify,
Widget child,
}) : _value = value,
_updateShouldNotify = updateShouldNotify,
super(key: key, child: child);
/// The currently exposed value.
///
/// Mutating `value` should be avoided. Instead rebuild the widget tree
/// and replace [InheritedProvider] with one that holds the new value.
final T _value;
final UpdateShouldNotify<T> _updateShouldNotify;
@override
bool updateShouldNotify(InheritedProvider<T> oldWidget) {
if (_updateShouldNotify != null) {
return _updateShouldNotify(oldWidget._value, _value);
}
return oldWidget._value != _value;
}
}
4、获取状态
final counter = Provider.of<Counter>(context);
/// Obtains the nearest [Provider<T>] up its widget tree and returns its
/// value.
///
/// If [listen] is `true` (default), later value changes will trigger a new
/// [State.build] to widgets, and [State.didChangeDependencies] for
/// [StatefulWidget].
static T of<T>(BuildContext context, {bool listen = true}) {
// this is required to get generic Type
final type = _typeOf<InheritedProvider<T>>();
final provider = listen
? context.inheritFromWidgetOfExactType(type) as InheritedProvider<T>
: context.ancestorInheritedElementForWidgetOfExactType(type)?.widget
as InheritedProvider<T>;
if (provider == null) {
throw ProviderNotFoundError(T, context.widget.runtimeType);
}
return provider._value;
}