Flutter插件eblox的使用_EbloX是一个简单的 Flutter 状态管理库
Flutter插件eblox的使用_EbloX是一个简单的 Flutter 状态管理库
EbloX 是一个简单的 Flutter 状态管理库,类似于 Bloc,但它通过 Action 和 State 的概念将业务逻辑与 UI 分离开来,并大量使用了注解。它更简单、更可靠且更容易测试!

示例:通用计数器
添加依赖
在 pubspec.yaml 文件中添加以下依赖:
dependencies:
eblox:
eblox_annotation:
dev_dependencies:
build_runner:
eblox_generator:
然后运行以下命令生成代码:
flutter pub run build_runner watch --delete-conflicting-outputs
创建 counter_view_model.dart
import 'package:eblox/eblox.dart';
import 'package:eblox_annotation/eblox_annotation.dart';
import 'package:flutter/cupertino.dart';
part 'counter_view_model.g.dart';
@blox
class CounterVModel with Blox {
@StateX(name: 'CounterState')
int _counter = 0;
@ActionX(bind: 'CounterState')
void _add() async {
_counter++;
}
@ActionX(bind: 'CounterState')
void _sub() {
_counter--;
}
[@override](/user/override)
void dispose() {
super.dispose();
debugPrint('CounterVModel dispose...');
}
}
这段代码定义了一个简单的计数器模型,包含两个操作(_add 和 _sub),并自动生成对应的 State 类。
创建 UI
import 'package:eblox/blox.dart';
import 'package:flutter/material.dart';
import 'package:flutter/widgets.dart';
import 'blox/counter_view_model.dart';
class CounterPage extends StatelessWidget {
const CounterPage({Key? key}) : super(key: key);
[@override](/user/override)
Widget build(BuildContext context) {
return Scaffold(
body: SafeArea(
child: BloxBuilder<CounterVModel, CounterState>(
inject: (injection) => injection.inject(CounterVModel()),
builder: (count) {
return Center(
child: Column(
mainAxisSize: MainAxisSize.min,
children: [
Text("$count"),
ElevatedButton(
onPressed: () {
$$<CounterVModel>(AddAction());
},
child: const Text("+"),
),
ElevatedButton(
onPressed: () {
$$<CounterVModel>(SubAction());
},
child: const Text("-"),
),
],
),
);
},
),
),
);
}
}
这里使用了 BloxBuilder 来监听状态变化,并根据状态更新 UI。
使用说明
创建 ViewModel
我们需要创建一个类并混入 Blox,这是类似 MVVM 中的 ViewModel。注意需要为该类添加 @blox 注解。如果需要外部访问由 @StateX 注解生成的状态,还需要混入 _$className,例如:
class CounterVModel with Blox, _$CounterVModel {
// ...
}
然后可以通过 $<CounterVModel>().counter 访问状态。
使用 @StateX
@StateX 用于装饰我们所需的状态,它会自动为我们生成一个带有指定名称的 State 类,用于封装修改后的数据。
@StateX(name: 'CounterState')
int _counter = 0;
如果不指定名称,则会根据默认规则生成 State 类名。
使用 @ActionX
@ActionX 用于生成 Action 类,可以指定名称,并通过 bind 指定与哪个 State 类关联。同时,它还会将装饰的方法与生成的 Action 关联起来,当发送 Action 时调用该方法。
@ActionX(bind: 'CounterState')
void _add() async {
_counter++;
}
异步状态 @AsyncX
除了同步状态外,还支持异步状态,使用 @AsyncX 装饰:
@AsyncX(name: 'SongListState')
SongListModel _songModel = SongListModel();
@bindAsync
@ActionX(bind: 'SongListState')
BloxAsyncTask<SongListModel> _search(String name) {
return () {
return SearchService.search(name);
};
}
UI 中处理异步状态
在 UI 中,我们可以使用 BloxView 来处理异步状态,它提供了 onLoading、onEmpty、onError 和 builder 方法来处理加载状态和数据展示。
class SearchPage extends StatelessWidget {
SearchPage({Key? key}) : super(key: key);
final TextEditingController _controller = TextEditingController();
[@override](/user/override)
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: const Text('Song search')),
body: SafeArea(
child: Column(
children: [
TextField(
controller: _controller,
decoration: InputDecoration(
contentPadding: const EdgeInsets.symmetric(horizontal: 16),
suffix: IconButton(
icon: const Icon(Icons.search_rounded),
onPressed: () {
if (_controller.text.isNotEmpty) {
$$<SearchVModel>(SearchAction(_controller.text));
}
},
),
),
),
Flexible(
child: BloxView<SearchVModel, SongListState<SongListModel>>(
create: () => SearchVModel(),
onLoading: () => const Center(child: CircularProgressIndicator()),
onEmpty: () => const Center(child: Text("Empty")),
builder: (state) {
return ListView.builder(
itemCount: state.data.songs.length,
itemBuilder: (ctx, i) {
return Container(
alignment: Alignment.center,
height: 40,
child: Text(
state.data.songs[i],
style: const TextStyle(color: Colors.blueGrey, fontSize: 20),
),
);
},
);
},
),
),
],
),
),
);
}
}
注意事项
如果希望 onEmpty 生效,则需要确保自定义的数据类型实现了 BloxData 接口:
class SongListModel with BloxData {
SongListModel({UnmodifiableListView<String>? songs}) {
if (songs != null) this.songs = songs;
}
UnmodifiableListView<String> songs = UnmodifiableListView([]);
[@override](/user/override)
bool get isEmpty => songs.isEmpty;
}更多关于Flutter插件eblox的使用_EbloX是一个简单的 Flutter 状态管理库的实战教程也可以访问 https://www.itying.com/category-92-b0.html

