Provider 框架概述
来源
Provider 是一个状态管理框架,由 Remi Rousselet 开发。它是对 Flutter 官方推荐的 InheritedWidget 的封装和简化,让状态管理变得更加简单和易用。
核心概念
Provider 基于 Flutter 的 InheritedWidget
机制,通过依赖注入的方式在 Widget 树中传递数据,实现状态管理。
Provider 在 Flutter 中的使用方法
1. 基本设置
添加依赖
在 pubspec.yaml
中添加:
dependencies:
provider: ^6.0.5
导入包
import 'package:provider/provider.dart';
2. 创建数据模型(Model)
// lib/models/user_model.dart
class UserModel {
String name;
int age;
UserModel({required this.name, required this.age});
void updateName(String newName) {
name = newName;
}
void updateAge(int newAge) {
age = newAge;
}
}
3. 创建 ChangeNotifier
// lib/providers/user_provider.dart
import 'package:flutter/foundation.dart';
import '../models/user_model.dart';
class UserProvider extends ChangeNotifier {
UserModel _user = UserModel(name: '张三', age: 25);
UserModel get user => _user;
void updateUserName(String newName) {
_user.updateName(newName);
notifyListeners(); // 通知所有监听者数据已更新
}
void updateUserAge(int newAge) {
_user.updateAge(newAge);
notifyListeners();
}
void updateUser(UserModel newUser) {
_user = newUser;
notifyListeners();
}
}
4. 在应用根级别设置 Provider
// lib/main.dart
import 'package:flutter/material.dart';
import 'package:provider/provider.dart';
import 'providers/user_provider.dart';
void main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
Widget build(BuildContext context) {
return MultiProvider(
providers: [
ChangeNotifierProvider(create: (_) => UserProvider()),
// 可以添加更多 Provider
// ChangeNotifierProvider(create: (_) => ThemeProvider()),
// ChangeNotifierProvider(create: (_) => LanguageProvider()),
],
child: MaterialApp(
title: 'Provider Demo',
home: HomePage(),
),
);
}
}
5. 在 Widget 中使用 Provider
方式一:使用 Consumer(推荐用于局部更新)
// lib/pages/home_page.dart
import 'package:flutter/material.dart';
import 'package:provider/provider.dart';
import '../providers/user_provider.dart';
class HomePage extends StatelessWidget {
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: Text('Provider Demo')),
body: Column(
children: [
// 使用 Consumer 监听特定数据变化
Consumer<UserProvider>(
builder: (context, userProvider, child) {
return Card(
child: ListTile(
title: Text('姓名: ${userProvider.user.name}'),
subtitle: Text('年龄: ${userProvider.user.age}'),
),
);
},
),
// 使用 Selector 只监听特定字段变化
Selector<UserProvider, String>(
selector: (context, provider) => provider.user.name,
builder: (context, name, child) {
return Text('当前用户: $name');
},
),
// 按钮区域
ElevatedButton(
onPressed: () {
context.read<UserProvider>().updateUserName('李四');
},
child: Text('更新姓名'),
),
ElevatedButton(
onPressed: () {
context.read<UserProvider>().updateUserAge(30);
},
child: Text('更新年龄'),
),
],
),
);
}
}
方式二:使用 Provider.of
class UserInfoWidget extends StatelessWidget {
Widget build(BuildContext context) {
// 监听变化(当数据变化时会重建 Widget)
final userProvider = Provider.of<UserProvider>(context);
return Column(
children: [
Text('姓名: ${userProvider.user.name}'),
Text('年龄: ${userProvider.user.age}'),
],
);
}
}
class UserActionWidget extends StatelessWidget {
Widget build(BuildContext context) {
// 不监听变化,只获取实例
final userProvider = Provider.of<UserProvider>(context, listen: false);
return ElevatedButton(
onPressed: () {
userProvider.updateUserName('王五');
},
child: Text('修改姓名'),
);
}
}
6. 高级用法
多个 Provider 的组合
// lib/providers/app_state.dart
class AppState extends ChangeNotifier {
UserProvider _userProvider;
ThemeProvider _themeProvider;
AppState() {
_userProvider = UserProvider();
_themeProvider = ThemeProvider();
}
UserProvider get userProvider => _userProvider;
ThemeProvider get themeProvider => _themeProvider;
}
// 在 main.dart 中使用
MultiProvider(
providers: [
ChangeNotifierProvider(create: (_) => AppState()),
],
child: MaterialApp(...),
)
使用 ProxyProvider 进行依赖注入
// 当某个 Provider 依赖另一个 Provider 时
MultiProvider(
providers: [
ChangeNotifierProvider(create: (_) => UserProvider()),
ChangeNotifierProxyProvider<UserProvider, UserService>(
create: (_) => UserService(),
update: (context, userProvider, previous) =>
UserService(userProvider: userProvider),
),
],
child: MaterialApp(...),
)
7. 实际项目中的最佳实践
项目结构示例
lib/
├── providers/
│ ├── user_provider.dart
│ ├── theme_provider.dart
│ ├── language_provider.dart
│ └── app_provider.dart
├── models/
│ ├── user_model.dart
│ └── app_settings.dart
├── pages/
│ ├── home_page.dart
│ └── profile_page.dart
└── main.dart
完整的 Provider 示例
// lib/providers/app_provider.dart
import 'package:flutter/foundation.dart';
import '../models/app_settings.dart';
class AppProvider extends ChangeNotifier {
AppSettings _settings = AppSettings(
isDarkMode: false,
language: 'zh_CN',
notificationsEnabled: true,
);
AppSettings get settings => _settings;
void toggleDarkMode() {
_settings = _settings.copyWith(isDarkMode: !_settings.isDarkMode);
notifyListeners();
}
void updateLanguage(String language) {
_settings = _settings.copyWith(language: language);
notifyListeners();
}
void toggleNotifications() {
_settings = _settings.copyWith(
notificationsEnabled: !_settings.notificationsEnabled
);
notifyListeners();
}
}
// lib/models/app_settings.dart
class AppSettings {
final bool isDarkMode;
final String language;
final bool notificationsEnabled;
AppSettings({
required this.isDarkMode,
required this.language,
required this.notificationsEnabled,
});
AppSettings copyWith({
bool? isDarkMode,
String? language,
bool? notificationsEnabled,
}) {
return AppSettings(
isDarkMode: isDarkMode ?? this.isDarkMode,
language: language ?? this.language,
notificationsEnabled: notificationsEnabled ?? this.notificationsEnabled,
);
}
}
8. Provider 的优势和适用场景
优势
- 简单易用:API 简洁,学习成本低
- 性能优化:支持局部更新,避免不必要的重建
- 类型安全:编译时类型检查
- 官方推荐:Flutter 团队推荐的状态管理方案
适用场景
- 中小型应用的状态管理
- 需要简单状态管理的场景
- 团队对状态管理要求不复杂的项目
- 快速原型开发
9. 注意事项
- 避免过度使用:不要为每个小功能都创建 Provider
- 合理分层:将相关的状态放在同一个 Provider 中
- 性能考虑:使用
Selector
和Consumer
进行局部更新 - 内存管理:及时释放不需要的监听器
Provider 是 Flutter 中最受欢迎的状态管理方案之一,特别适合中小型项目。它提供了简单而强大的状态管理能力,是 Flutter 开发者的首选工具。