在 main.dart 文件中添加了对 Flutter 应用程序结构的详细注释,增强代码可读性。 在 basic_provider_page.dart 文件中调整了注释格式,确保一致性和清晰性。
352 lines
9.8 KiB
Dart
352 lines
9.8 KiB
Dart
import 'package:flutter/material.dart';
|
|
import 'package:provider/provider.dart';
|
|
|
|
// 修改UserInfo为可变的
|
|
class UserInfo extends ChangeNotifier {
|
|
String _name;
|
|
int _age;
|
|
String _email;
|
|
|
|
UserInfo({
|
|
required String name,
|
|
required int age,
|
|
required String email,
|
|
}) : _name = name,
|
|
_age = age,
|
|
_email = email;
|
|
|
|
String get name => _name;
|
|
|
|
int get age => _age;
|
|
|
|
String get email => _email;
|
|
|
|
void updateName(String newName) {
|
|
_name = newName;
|
|
notifyListeners();
|
|
}
|
|
|
|
void incrementAge() {
|
|
_age++;
|
|
notifyListeners();
|
|
}
|
|
|
|
void updateEmail(String newEmail) {
|
|
_email = newEmail;
|
|
notifyListeners();
|
|
}
|
|
}
|
|
|
|
// 修改AppConfig为可变的
|
|
class AppConfig extends ChangeNotifier {
|
|
String _theme;
|
|
String _language;
|
|
|
|
AppConfig({
|
|
required String theme,
|
|
required String language,
|
|
}) : _theme = theme,
|
|
_language = language;
|
|
|
|
String get theme => _theme;
|
|
|
|
String get language => _language;
|
|
|
|
void toggleTheme() {
|
|
_theme = _theme == 'light' ? 'dark' : 'light';
|
|
notifyListeners();
|
|
}
|
|
|
|
void toggleLanguage() {
|
|
_language = _language == 'en' ? 'zh' : 'en';
|
|
notifyListeners();
|
|
}
|
|
}
|
|
|
|
class BasicProviderPage extends StatelessWidget {
|
|
const BasicProviderPage({super.key});
|
|
|
|
@override
|
|
Widget build(BuildContext context) {
|
|
return MultiProvider(
|
|
providers: [
|
|
// 提供单个值
|
|
Provider<String>.value(value: 'Hello from Basic Provider!'),
|
|
|
|
// 提供可变的用户信息
|
|
ChangeNotifierProvider(
|
|
create: (_) => UserInfo(
|
|
name: 'John Doe',
|
|
age: 30,
|
|
email: 'john@example.com',
|
|
),
|
|
),
|
|
|
|
// 提供可变的配置信息
|
|
ChangeNotifierProvider(
|
|
create: (_) => AppConfig(
|
|
theme: 'light',
|
|
language: 'en',
|
|
),
|
|
),
|
|
],
|
|
child: Scaffold(
|
|
appBar: AppBar(title: const Text('Basic Provider')),
|
|
body: const SingleChildScrollView(
|
|
child: Padding(
|
|
padding: EdgeInsets.all(16.0),
|
|
child: Column(
|
|
crossAxisAlignment: CrossAxisAlignment.start,
|
|
children: [
|
|
WatchExample(),
|
|
SizedBox(height: 20),
|
|
ReadExample(),
|
|
SizedBox(height: 20),
|
|
SelectExample(),
|
|
SizedBox(height: 20),
|
|
ConsumerExample(),
|
|
SizedBox(height: 20),
|
|
OfExample(),
|
|
SizedBox(height: 20),
|
|
UpdateSection(),
|
|
],
|
|
),
|
|
),
|
|
),
|
|
),
|
|
);
|
|
}
|
|
}
|
|
|
|
// 添加新的更新部分
|
|
class UpdateSection extends StatelessWidget {
|
|
const UpdateSection({super.key});
|
|
|
|
@override
|
|
Widget build(BuildContext context) {
|
|
return Card(
|
|
child: Padding(
|
|
padding: const EdgeInsets.all(8.0),
|
|
child: Column(
|
|
crossAxisAlignment: CrossAxisAlignment.start,
|
|
children: [
|
|
const Text('Update Examples:', style: TextStyle(fontWeight: FontWeight.bold)),
|
|
const SizedBox(height: 10),
|
|
|
|
// 用户信息更新按钮
|
|
const Text('User Info Updates:'),
|
|
Row(
|
|
mainAxisAlignment: MainAxisAlignment.spaceAround,
|
|
children: [
|
|
ElevatedButton(
|
|
onPressed: () {
|
|
context.read<UserInfo>().updateName(context.read<UserInfo>().name == 'John Doe' ? 'Jane Doe' : 'John Doe');
|
|
},
|
|
child: const Text('Toggle Name'),
|
|
),
|
|
ElevatedButton(
|
|
onPressed: () => context.read<UserInfo>().incrementAge(),
|
|
child: const Text('Increment Age'),
|
|
),
|
|
ElevatedButton(
|
|
onPressed: () {
|
|
final currentEmail = context.read<UserInfo>().email;
|
|
context
|
|
.read<UserInfo>()
|
|
.updateEmail(currentEmail == 'john@example.com' ? 'jane@example.com' : 'john@example.com');
|
|
},
|
|
child: const Text('Toggle Email'),
|
|
),
|
|
],
|
|
),
|
|
const SizedBox(height: 10),
|
|
|
|
// 配置更新按钮
|
|
const Text('App Config Updates:'),
|
|
Row(
|
|
mainAxisAlignment: MainAxisAlignment.spaceAround,
|
|
children: [
|
|
ElevatedButton(
|
|
onPressed: () => context.read<AppConfig>().toggleTheme(),
|
|
child: const Text('Toggle Theme'),
|
|
),
|
|
ElevatedButton(
|
|
onPressed: () => context.read<AppConfig>().toggleLanguage(),
|
|
child: const Text('Toggle Language'),
|
|
),
|
|
],
|
|
),
|
|
|
|
// 实时显示当前值
|
|
const SizedBox(height: 10),
|
|
const Text('Current Values:'),
|
|
Consumer<UserInfo>(
|
|
builder: (context, userInfo, _) => Column(
|
|
crossAxisAlignment: CrossAxisAlignment.start,
|
|
children: [
|
|
Text('Name: ${userInfo.name}'),
|
|
Text('Age: ${userInfo.age}'),
|
|
Text('Email: ${userInfo.email}'),
|
|
],
|
|
),
|
|
),
|
|
const SizedBox(height: 5),
|
|
Consumer<AppConfig>(
|
|
builder: (context, config, _) => Column(
|
|
crossAxisAlignment: CrossAxisAlignment.start,
|
|
children: [
|
|
Text('Theme: ${config.theme}'),
|
|
Text('Language: ${config.language}'),
|
|
],
|
|
),
|
|
),
|
|
],
|
|
),
|
|
),
|
|
);
|
|
}
|
|
}
|
|
|
|
// 使用 watch 方式访问数据(会监听变化)
|
|
class WatchExample extends StatelessWidget {
|
|
const WatchExample({super.key});
|
|
|
|
@override
|
|
Widget build(BuildContext context) {
|
|
final String message = context.watch<String>();
|
|
final userInfo = context.watch<UserInfo>();
|
|
|
|
return Card(
|
|
child: Padding(
|
|
padding: const EdgeInsets.all(8.0),
|
|
child: Column(
|
|
crossAxisAlignment: CrossAxisAlignment.start,
|
|
children: [
|
|
const Text('Watch Example:', style: TextStyle(fontWeight: FontWeight.bold)),
|
|
Text('Message: $message'),
|
|
Text('User: ${userInfo.name}, Age: ${userInfo.age}'),
|
|
],
|
|
),
|
|
),
|
|
);
|
|
}
|
|
}
|
|
|
|
// 使用 read 方式访问数据(不会监听变化)
|
|
class ReadExample extends StatelessWidget {
|
|
const ReadExample({super.key});
|
|
|
|
@override
|
|
Widget build(BuildContext context) {
|
|
// read 适合在事件处理中使用
|
|
final userInfo = context.read<UserInfo>();
|
|
return Card(
|
|
child: Padding(
|
|
padding: const EdgeInsets.all(8.0),
|
|
child: Column(
|
|
crossAxisAlignment: CrossAxisAlignment.start,
|
|
children: [
|
|
Text('Read Example: ${userInfo.name}', style: TextStyle(fontWeight: FontWeight.bold)),
|
|
ElevatedButton(
|
|
onPressed: () {
|
|
final userInfo = context.read<UserInfo>();
|
|
ScaffoldMessenger.of(context).showSnackBar(
|
|
SnackBar(content: Text('Email: ${userInfo.email}')),
|
|
);
|
|
},
|
|
child: const Text('Show User Email'),
|
|
),
|
|
],
|
|
),
|
|
),
|
|
);
|
|
}
|
|
}
|
|
|
|
// 使用 select 方式访问数据(只监听特定字段)
|
|
class SelectExample extends StatelessWidget {
|
|
const SelectExample({super.key});
|
|
|
|
@override
|
|
Widget build(BuildContext context) {
|
|
final language = context.select((AppConfig config) => config.language);
|
|
final theme = context.select((AppConfig config) => config.theme);
|
|
|
|
return Card(
|
|
child: Padding(
|
|
padding: const EdgeInsets.all(8.0),
|
|
child: Column(
|
|
crossAxisAlignment: CrossAxisAlignment.start,
|
|
children: [
|
|
const Text('Select Example:', style: TextStyle(fontWeight: FontWeight.bold)),
|
|
Text('Language: $language'),
|
|
Text('Theme: $theme'),
|
|
],
|
|
),
|
|
),
|
|
);
|
|
}
|
|
}
|
|
|
|
// 使用 Consumer 方式访问数据
|
|
class ConsumerExample extends StatelessWidget {
|
|
const ConsumerExample({super.key});
|
|
|
|
@override
|
|
Widget build(BuildContext context) {
|
|
return Card(
|
|
child: Padding(
|
|
padding: const EdgeInsets.all(8.0),
|
|
child: Column(
|
|
crossAxisAlignment: CrossAxisAlignment.start,
|
|
children: [
|
|
const Text('Consumer Example:', style: TextStyle(fontWeight: FontWeight.bold)),
|
|
Consumer<UserInfo?>(
|
|
builder: (context, userInfo, child) {
|
|
if (userInfo == null) {
|
|
return const Text('UserInfo not provided');
|
|
}
|
|
return Column(
|
|
crossAxisAlignment: CrossAxisAlignment.start,
|
|
children: [
|
|
Text('Name: ${userInfo.name}'),
|
|
Text('Age: ${userInfo.age}'),
|
|
Text('Email: ${userInfo.email}'),
|
|
],
|
|
);
|
|
},
|
|
),
|
|
],
|
|
),
|
|
),
|
|
);
|
|
}
|
|
}
|
|
|
|
// 使用 Provider.of 方式访问数据
|
|
class OfExample extends StatelessWidget {
|
|
const OfExample({super.key});
|
|
|
|
@override
|
|
Widget build(BuildContext context) {
|
|
// listen: false 类似于 read
|
|
final appConfig = Provider.of<AppConfig>(context, listen: false);
|
|
// listen: true 类似于 watch
|
|
final userInfo = Provider.of<UserInfo>(context, listen: true);
|
|
|
|
return Card(
|
|
child: Padding(
|
|
padding: const EdgeInsets.all(8.0),
|
|
child: Column(
|
|
crossAxisAlignment: CrossAxisAlignment.start,
|
|
children: [
|
|
const Text('Provider.of Example:', style: TextStyle(fontWeight: FontWeight.bold)),
|
|
Text('Theme: ${appConfig.theme}'),
|
|
Text('User: ${userInfo.name}'),
|
|
],
|
|
),
|
|
),
|
|
);
|
|
}
|
|
}
|