Flutter状态管理插件statescope的使用
Flutter状态管理插件statescope的使用
StateScope
StateScope
是 Simple State Management
的一个分支。它利用了 InheritedNotifier
来实现非常简单的状态管理。
特点
- 极其容易使用。
- 轻量且性能良好。
- 惰性创建状态。
使用方法
首先,你需要将状态存储在一个扩展了 ChangeNotifier
的类中:
class Counter extends ChangeNotifier {
int count = 0;
void countUp() {
count++;
notifyListeners(); // 通知所有监听者状态已更改
}
}
然后,将这个类放入 StateScope
的 creator
中:
StateScope(
creator: () => Counter(), // 创建一个新的Counter实例
child: Builder(
builder: (context) {
// 使用watch()来监听状态变化并重建widget
final counter = context.watch<Counter>();
return Column(
children: [
Text('${counter.count}'), // 显示当前计数
ElevatedButton(
onPressed: () {
// 使用read()来获取状态但不重建widget
context.read<Counter>().countUp();
},
child: Text('Count up'),
),
],
);
},
),
);
如果希望立即创建状态而不是惰性创建,可以设置 lazy
参数为 false
:
StateScope(
lazy: false,
creator: () => Counter(),
child: Builder(
builder: (context) {
final counter = context.watch<Counter>();
return Column(
children: [
Text('${counter.count}'),
ElevatedButton(
onPressed: () {
context.read<Counter>().countUp();
},
child: Text('Count up'),
),
],
);
},
),
);
完整示例
以下是一个完整的示例,展示了如何使用 StateScope
管理复杂的用户认证和计数器状态。
import 'dart:async';
import 'dart:math';
import 'package:flutter/material.dart';
import 'package:statescope/statescope.dart';
void main() {
runApp(const App());
}
class App extends StatelessWidget {
const App({super.key});
[@override](/user/override)
Widget build(BuildContext context) {
return MaterialApp(
title: 'Authed Counter',
theme: ThemeData.light(),
darkTheme: ThemeData.dark(),
themeMode: ThemeMode.system,
debugShowCheckedModeBanner: false,
home: StateScope(
creator: () => AuthState(),
child: Builder(builder: (context) {
final authState = context.watch<AuthState>();
if (authState.isLoggedIn) {
return StateScope(
creator: () => AppState(),
child: const HomePage(title: 'Authed Counter'),
);
} else {
return const LoginPage();
}
}),
),
);
}
}
class HomePage extends StatelessWidget {
const HomePage({super.key, required this.title});
final String title;
[@override](/user/override)
Widget build(BuildContext context) {
final appState = context.watch<AppState>();
return Scaffold(
appBar: PreferredSize(
preferredSize: const Size.fromHeight(kToolbarHeight),
child: AppBar(
title: Text(title, style: TextStyle(color: appState.textColor)),
backgroundColor: appState.backgroundColor,
actions: [
ElevatedButton(
onPressed: () {
context.read<AuthState>().logout();
},
child: const Text('Logout'),
),
],
),
),
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
const Text('You have pushed the button this many times:'),
Text(appState.count.toString()),
],
),
),
floatingActionButton: FloatingActionButton(
onPressed: () {
context.read<AppState>().incrementCounter();
},
tooltip: 'Increment',
backgroundColor: appState.backgroundColor,
child: Icon(Icons.add, color: appState.textColor),
),
);
}
}
class LoginPage extends StatelessWidget {
const LoginPage({super.key});
[@override](/user/override)
Widget build(BuildContext context) {
final authState = context.watch<AuthState>();
return Scaffold(
body: Center(
child: authState.isLogging
? const CircularProgressIndicator()
: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
OutlinedButton(
onPressed: () {
context.read<AuthState>().login();
},
child: const Text('Login'),
),
if (authState.error != null)
Padding(
padding: const EdgeInsets.all(8.0),
child: Text(
authState.error!,
style: const TextStyle(color: Colors.red),
),
),
],
),
),
);
}
}
enum _AuthState { loggedOut, logging, loggedIn }
class AuthState extends ChangeNotifier {
var _authState = _AuthState.loggedOut;
String? error;
bool get isLogging => _authState == _AuthState.logging;
bool get isLoggedIn => _authState == _AuthState.loggedIn;
void login() {
unawaited(_login());
}
Future<void> _login() async {
error = null;
_authState = _AuthState.logging;
notifyListeners();
try {
await Future.delayed(const Duration(milliseconds: 500));
final rand = Random().nextDouble();
if (rand > 0.9) {
throw Exception("intentional random error example");
}
} catch (e) {
error = 'Login failed: ${e.toString()}';
logout();
return;
}
_authState = _AuthState.loggedIn;
notifyListeners();
}
void logout() {
_authState = _AuthState.loggedOut;
notifyListeners();
}
}
const _colors = [
Colors.blue,
Colors.red,
Colors.green,
Colors.purple,
Colors.yellow,
];
class AppState extends ChangeNotifier {
int _count = 0;
int get count => _count;
void incrementCounter() {
_count++;
_backgroundColor = _colors[count % 5];
notifyListeners();
}
Color _backgroundColor = Colors.blue;
Color get backgroundColor => _backgroundColor;
Color get textColor =>
_backgroundColor == Colors.yellow ? Colors.black87 : Colors.white;
}
更多关于Flutter状态管理插件statescope的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html
更多关于Flutter状态管理插件statescope的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html
在Flutter开发中,状态管理是一个核心问题,特别是在构建复杂应用时。StateScope
是一个相对较新的状态管理库,它提供了一种简洁而强大的方式来管理 Flutter 应用中的状态。以下是一个简单的示例,展示了如何在 Flutter 项目中使用 StateScope
进行状态管理。
首先,确保你的 Flutter 项目中已经添加了 state_scope
依赖。在你的 pubspec.yaml
文件中添加以下依赖:
dependencies:
flutter:
sdk: flutter
state_scope: ^最新版本号 # 请替换为实际的最新版本号
然后,运行 flutter pub get
来安装依赖。
接下来,我们将展示一个简单的示例,其中包含一个计数器应用,使用 StateScope
来管理计数器状态。
1. 创建主应用组件
import 'package:flutter/material.dart';
import 'package:state_scope/state_scope.dart';
void main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
home: ScopeHost(
scope: CounterScope(),
child: CounterPage(),
),
);
}
}
2. 定义状态作用域
创建一个新的 Dart 文件 counter_scope.dart
来定义 CounterScope
:
import 'package:state_scope/state_scope.dart';
class CounterScope extends Scope {
var _count = 0;
int get count => _count;
void increment() {
_count++;
notify();
}
}
3. 创建显示计数器的页面
import 'package:flutter/material.dart';
import 'package:state_scope/state_scope.dart';
import 'counter_scope.dart';
class CounterPage extends StatelessWidget {
@override
Widget build(BuildContext context) {
final counterScope = useScope<CounterScope>();
return Scaffold(
appBar: AppBar(
title: Text('Counter App'),
),
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Text(
'You have pushed the button this many times:',
),
Text(
'${counterScope.count}',
style: Theme.of(context).textTheme.headline4,
),
],
),
),
floatingActionButton: FloatingActionButton(
onPressed: () {
counterScope.increment();
},
tooltip: 'Increment',
child: Icon(Icons.add),
),
);
}
}
解释
-
MyApp
:主应用组件,使用ScopeHost
包装CounterScope
并将其传递给CounterPage
。 -
CounterScope
:自定义的状态作用域,包含一个整数_count
和一个increment
方法来更新计数并通知监听器。 -
CounterPage
:使用useScope<CounterScope>()
从ScopeHost
获取CounterScope
实例,并显示当前的计数。同时,使用一个浮动操作按钮来调用increment
方法增加计数。
通过这种方式,你可以使用 StateScope
在 Flutter 应用中有效地管理状态。StateScope
提供了简洁的 API 和高效的状态更新机制,非常适合用于构建复杂且响应迅速的 Flutter 应用。