flutter_provider_demo
This commit is contained in:
360
lib/pages/basic_provider_page.dart
Normal file
360
lib/pages/basic_provider_page.dart
Normal file
@ -0,0 +1,360 @@
|
||||
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}'),
|
||||
],
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user