StoreScope
一个轻量级的 Flutter 状态管理库,专注于提供简洁的状态生命周期管理和局部状态管理。
特性
- 🚀 简洁的状态生命周期管理
- 🔄 基于 Widget 树的局部状态管理
- 🔗 支持状态之间的相互依赖
- 🧹 自动管理状态的生命周期和资源释放
- 🎯 专注于状态管理,不包含响应式机制
快速开始
1. 在应用的根 Widget 中添加 StoreScope:
void main() {
runApp(
StoreScope(
child: MyApp(),
),
);
}
2. 创建简单的状态类:
使用 ValueNotifier 创建响应式状态:
class Counter {
final _count = ValueNotifier<int>(0);
ValueNotifier<int> get count => _count;
void increment() {
_count.value++;
}
}
3. 创建 Provider:
// 作用域实例:跟随绑定它的页面/Widget,最后一个使用者销毁时自动析构(见方式二)
final counterProvider = Provider.from(
(space) => Counter(),
);
// 全局实例:跟随 Store 生命周期,直到 StoreScope 被移除;用 context.read 读取(见方式一)
final sharedCounterProvider = Provider.shared(
(space) => Counter(),
);
4. 在页面中使用响应式状态:
方式一:使用 Provider.shared + context.read(全局状态)
class Home extends StatelessWidget {
@override
Widget build(context) {
// 用 read 读取全局实例,它会一直存在于内存中,直到 StoreScope 被移除
var counter = context.read(sharedCounterProvider);
return Scaffold(
appBar: AppBar(
title: ValueListenableBuilder<int>(
valueListenable: counter.count,
builder: (_, count, __) {
return Text('Count: $count');
},
),
),
floatingActionButton: FloatingActionButton(
child: Icon(Icons.add),
onPressed: counter.increment
),
);
}
}
class Other extends StatelessWidget {
@override
Widget build(BuildContext context) {
// 在其他页面中也可以访问同一个全局状态
final counter = context.read(sharedCounterProvider);
return Scaffold(
body: Center(
child: ValueListenableBuilder<int>(
valueListenable: counter.count,
builder: (_, count, __) {
return Text('Count: $count');
},
),
),
);
}
}
方式二:使用 bind(自动销毁)
class Home extends StatelessWidget with ScopedSpaceStatelessMixin{
@override
Widget buildWithSpace(BuildContext context, StoreSpace space) {
// 在所有绑定的页面销毁时自动释放counter
var counter = space.bind(counterProvider);
return Scaffold(
appBar: AppBar(
title: ValueListenableBuilder<int>(
valueListenable: counter.count,
builder: (_, count, __) {
return Text('Count: $count');
},
),
),
floatingActionButton: FloatingActionButton(
child: Icon(Icons.add),
onPressed: counter.increment
),
);
}
}
class Other extends StatelessWidget with ScopedSpaceStatelessMixin{
@override
Widget buildWithSpace(BuildContext context, StoreSpace space) {
// 在所有绑定的页面销毁时自动释放counter
var counter = space.bind(counterProvider);
return Scaffold(
body: Center(
child: ValueListenableBuilder<int>(
valueListenable: counter.count,
builder: (_, count, __) {
return Text('Count: $count');
},
),
),
);
}
}
高级用法
带参数的 Provider
// 定义带参数的 Provider
final userProvider = Provider.withArgument<User, int>((space, int userId) {
return User(userId: userId);
});
// 使用
final user = space.bind(userProvider(42));
状态依赖
final userProfileProvider = ViewModelProvider((space) {
final user = space.bind(userProvider(42));
final settings = space.bind(settingsProvider);
return UserProfileViewModel(user, settings);
});
ViewModel
ViewModel 是 StoreScope 中的核心组件,它提供了完整的状态生命周期管理和资源清理机制.
1. 生命周期管理
class CounterViewModel extends ViewModel {
final _count = ValueNotifier<int>(0);
ValueNotifier<int> get count => _count;
@override
void init() {
super.init();
// 初始化逻辑,比如订阅数据流、初始化状态等
_count.value = 10; // 设置初始值
}
void increment() => _count.value++;
@override
void dispose() {
_count.dispose(); // 清理资源
super.dispose(); // 必须调用 super.dispose()
}
}
2. 资源自动管理
ViewModel 提供了多种方式管理资源的生命周期:
class NetworkViewModel extends ViewModel {
Timer? _timer;
StreamSubscription? _subscription;
@override
void init() {
super.init();
// 方式一:添加订阅,自动取消
_subscription = someStream.listen((data) {
// 处理数据
});
addSubscription(_subscription!);
// 方式二:添加任意可关闭资源
addCloseable(() {
print('清理自定义资源');
});
// 方式三:带键的资源管理
addKeyedCloseable('timer', () {
_timer?.cancel();
});
// 如果添加了同键的资源,旧的会被立即清理
addKeyedCloseable('timer', () {
_timer = Timer.periodic(Duration(seconds: 1), (timer) {
// 新的定时器逻辑
});
});
}
}
3. 使用ViewModelProvider:
final viewModelProvider = ViewModelProvider((space) => CounterViewModel());
// 使用
final viewModel = space.bind(viewModelProvider);
// 这将自动调用 ViewModel 的 init()
// 当销毁时也会自动调用 ViewModel 的 dispose()
4.带参数的 ViewModelProvide
// 单参数
final userViewModelProvider = ViewModelProvider.withArgument<UserViewModel, int>(
(space, int userId) => UserViewModel(userId),
);
// 双参数
final productViewModelProvider = ViewModelProvider.withArgument2<ProductViewModel, String, int>(
(space, String category, int page) => ProductViewModel(category, page),
);
//更多参数也支持
// 使用
final userVM = space.bind(userViewModelProvider(42));
final productVM = space.bind(productViewModelProvider('electronics', 1));
关于响应式
StoreScope 本身不包含任何响应式机制。它专注于状态管理,让响应式库可以专注于它们擅长的部分。你可以:
-
使用内置的响应式类:
- ValueNotifier
- ChangeNotifier
-
使用第三方响应式库:
- solidart
- signals
- flutter_bloc
- 等等
这样的设计让 StoreScope 保持简单和专注,同时又能与任何响应式库完美配合。
更多介绍
Libraries
- store_scope
- Support for doing something awesome.