详细了解flutter中provider的工作原理
让我们深入解析一下Provider
在Flutter中的工作原理,特别是如何利用InheritedWidget
实现高效的状态管理。
Provider
的工作原理
Provider
作为Flutter中一个流行的状态管理解决方案,其核心依赖于InheritedWidget
来实现状态共享。以下是Provider
工作原理的详细解析:
1. ChangeNotifier
与状态管理
ChangeNotifier
是一个简单的类,它提供了监听器的注册和通知功能。通过notifyListeners
方法,我们可以通知所有注册的监听器状态已经发生了变化。
dart
复制代码
class Counter with ChangeNotifier {
int _count = 0;
int get count => _count;
void increment() {
_count++;
notifyListeners();
}
}
2. ChangeNotifierProvider
提供状态
ChangeNotifierProvider
是一个InheritedNotifier
,它将ChangeNotifier
实例插入到Widget树中,并负责创建和销毁状态对象。ChangeNotifierProvider
的主要作用是将状态对象提供给子Widget。
dart
复制代码
ChangeNotifierProvider(
create: (context) => Counter(),
child: MyApp(),
)
3. InheritedNotifier
的实现
InheritedNotifier
继承自InheritedWidget
,并包含一个Listenable
(通常是ChangeNotifier
),它负责监听状态变化,并在状态变化时触发重建。
dart
复制代码
class InheritedNotifier<T extends Listenable> extends InheritedWidget {
final T notifier;
InheritedNotifier({
Key? key,
required this.notifier,
required Widget child,
}) : super(key: key, child: child);
@override
bool updateShouldNotify(InheritedNotifier<T> oldWidget) {
return oldWidget.notifier != notifier;
}
}
4. Consumer
和Provider.of
访问状态
子Widget可以通过Provider.of
方法直接访问状态,也可以通过Consumer
小部件监听状态变化。Consumer
小部件会在状态变化时自动重建,从而更新UI。
dart
复制代码
// 直接访问状态
final counter = Provider.of<Counter>(context);
// 监听状态变化
Consumer<Counter>(
builder: (context, counter, child) {
return Text('${counter.count}');
},
)
源码解析
让我们深入解析一下ChangeNotifierProvider
的源码实现:
-
ChangeNotifierProvider
ChangeNotifierProvider
是一个InheritedNotifier
,它将ChangeNotifier
与InheritedWidget
结合起来。dart 复制代码 class ChangeNotifierProvider<T extends ChangeNotifier> extends InheritedNotifier<T> { ChangeNotifierProvider({ Key? key, required T Function(BuildContext context) create, required Widget child, }) : super(key: key, notifier: create(context), child: child); static T of<T extends ChangeNotifier>(BuildContext context) { final provider = context.dependOnInheritedWidgetOfExactType<ChangeNotifierProvider<T>>(); return provider!.notifier!; } }
-
InheritedNotifier
InheritedNotifier
继承自InheritedWidget
,并包含一个Listenable
(通常是ChangeNotifier
)。dart 复制代码 class InheritedNotifier<T extends Listenable> extends InheritedWidget { final T notifier; InheritedNotifier({ Key? key, required this.notifier, required Widget child, }) : super(key: key, child: child); @override bool updateShouldNotify(InheritedNotifier<T> oldWidget) { return oldWidget.notifier != notifier; } }
完整示例
以下是一个完整的Flutter应用示例,展示了如何使用Provider
进行状态管理:
dart
复制代码
import 'package:flutter/material.dart';
import 'package:provider/provider.dart';
void main() => runApp(
ChangeNotifierProvider(
create: (context) => Counter(),
child: MyApp(),
),
);
class Counter with ChangeNotifier {
int _count = 0;
int get count => _count;
void increment() {
_count++;
notifyListeners();
}
}
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
home: CounterPage(),
);
}
}
class CounterPage extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: Text('Provider Example')),
body: Center(
child: Consumer<Counter>(
builder: (context, counter, child) {
return Text(
'Count: ${counter.count}',
style: TextStyle(fontSize: 24),
);
},
),
),
floatingActionButton: FloatingActionButton(
onPressed: () => Provider.of<Counter>(context, listen: false).increment(),
child: Icon(Icons.add),
),
);
}
}
在Provider
中,监听状态变化和通知状态变化的过程主要使用了观察者模式(Observer Pattern) 。此外,还结合了**依赖注入(Dependency Injection)**模式来简化状态管理。让我们深入分析这两个设计模式在Provider
中的应用。
观察者模式
定义
观察者模式是一种行为型设计模式,定义了对象之间的一对多依赖关系,使得一个对象的状态发生变化时,所有依赖于它的对象都会得到通知并自动更新。这在需要自动通知并更新界面的时候非常有用。
在Provider
中的应用
在Provider
中,ChangeNotifier
类实现了观察者模式。ChangeNotifier
维护了一组监听器,当状态发生变化时,通过notifyListeners
方法通知所有的监听器。
-
监听器的注册 当一个Widget需要监听状态变化时,它会将自身注册到
ChangeNotifier
中。dart 复制代码 class ChangeNotifier { List<VoidCallback> _listeners = []; void addListener(VoidCallback listener) { _listeners.add(listener); } void removeListener(VoidCallback listener) { _listeners.remove(listener); } void notifyListeners() { for (final listener in _listeners) { listener(); } } }
-
状态变化的通知 当状态发生变化时,调用
notifyListeners
方法通知所有注册的监听器。dart 复制代码 class Counter with ChangeNotifier { int _count = 0; int get count => _count; void increment() { _count++; notifyListeners(); } }
依赖注入模式
定义
依赖注入是一种设计模式,用于将对象的创建和依赖关系的管理外包给一个外部实体。这样可以减少类之间的耦合,使代码更容易测试和维护。
在Provider
中的应用
在Provider
中,通过ChangeNotifierProvider
将状态对象注入到Widget树中,供子Widget使用。这种方式减少了Widget之间的依赖关系,使得状态管理更加清晰。
-
提供状态对象
ChangeNotifierProvider
将状态对象插入到Widget树中,并提供给子Widget。dart 复制代码 ChangeNotifierProvider( create: (context) => Counter(), child: MyApp(), )
-
访问状态对象 子Widget可以通过
Provider.of
方法或Consumer
小部件访问状态对象。dart 复制代码 final counter = Provider.of<Counter>(context);
总结
Provider
在Flutter中的工作原理可以总结为以下几点:
- 状态管理:通过
ChangeNotifier
管理状态。 - 状态提供:通过
ChangeNotifierProvider
将状态对象插入到Widget树中。 - 状态访问:通过
Provider.of
和Consumer
访问和监听状态变化。 - 状态变化通知:通过
notifyListeners
通知所有注册的监听器状态变化。
- 观察者模式:
ChangeNotifier
管理监听器并通知状态变化。 - 依赖注入模式:
ChangeNotifierProvider
提供状态对象并将其注入到Widget树中。
在Provider
中,监听状态变化和通知状态变化主要使用了观察者模式。依赖注入模式用于简化状态管理和减少组件之间的耦合。
这种机制结合了ChangeNotifier
和InheritedWidget
的优点,提供了一种简洁且高效的状态管理方式,非常适合Flutter应用程序的开发。
转载自:https://juejin.cn/post/7382107891400261684