目录
1. BLoC (状态管理库中Star最高)
2. GetIt
1. BLoC (状态管理库中Star最高)
更多的是一种设计模式,按照这种设计模式可以实现很多种状态管理。
基于Stream / Observable范式。BLoC 依赖 Stream和 StreamController实现,组件通过Sinks发送更新状态的事件,然后再通过 Streams 通知其他组件更新。事件处理和通知刷新的业务逻辑都是由BLoC完成,从而实现业务逻辑与UI层的分离(有点类似 Redux),并且逻辑部分可以复用和可以单独进行单元测试。
添加依赖库
bloc插件
flutter_bloc插件
提供了BlocProvider、BlocBuilder、BlocListener、BlocConsumer、RepositoryProvider等。
bloc_package插件
快速在Flutter/Dart中实现BLoC模式的插件。
- 3个重要概念
- Cubit(继承自管理状态数据的BlocBase)
可以管理任意类型的数据,包括基本类型到复杂对象。
Cubit调用emit构建新的状态数据前需要给状态数据一个初始值。
当状态数据发生改变时会触发onChange回调,出错时会触发onError回调。
UI界面可以通过调用 Cubit 对外暴露的更新状态方法触发状态更新,而在 onChange 中会得到更新前后的状态,从而可以触发界面刷新。
例:
class CounterCubit extends Cubit<int> {
CounterCubit() : super(0);
void increment() => emit(state + 1);
void decrement() => emit(state - 1);
@override
void onChange(Change<int> change) {
super.onChange(change);
print(change);
}
@override
void onError(Object error, StackTrace stackTrace) {
print('$error, $stackTrace');
super.onError(error, stackTrace);
}
}
- BlocObserver(可以同时监听所有的Cubit的变化)
例:
class CounterCubit extends Cubit<int> {
CounterCubit({initial = 0}) : super(initial);
void increment() => emit(state + 1);
void decrement() => emit(state - 1);
}
class MyBlocObserver extends BlocObserver {
@override
void onCreate(BlocBase bloc) {
print('BloC Observer onCreate: ${bloc.state}');
super.onCreate(bloc);
}
@override
void onChange(BlocBase bloc, Change change) {
print('BloC Observer onChange: $change');
super.onChange(bloc, change);
}
@override
void onClose(BlocBase bloc) {
print('BloC Observer onClose: ${bloc.state}');
super.onClose(bloc);
}
@override
void onError(BlocBase bloc, Object error, StackTrace stackTrace) {
print('Bloc Observer onError: $error, $stackTrace');
super.onError(bloc, error, stackTrace);
}
@override
void onEvent(Bloc bloc, Object? event) {
print('Bloc Observer onEvent: $event, ${bloc.state}');
super.onEvent(bloc, event);
}
}
void main() {
Bloc.observer = MyBlocObserver();
final cubit = CounterCubit();
cubit.increment();
print('after increment: ${cubit.state}');
cubit.decrement();
print('after decrement: ${cubit.state}');
final anotherCubit = CounterCubit(10);
anotherCubit.increment();
cubit.close();
anotherCubit.close();
}
/*
控制台输出如下:
BloC Observer onCreate: 0
BloC Observer onChange: Change { currentState: 0, nextState: 1 }
BloC Observer onChange: Change { currentState: 1, nextState: 0 }
BloC Observer onCreate: 10
BloC Observer onChange: Change { currentState: 10, nextState: 11 }
BloC Observer onClose: 0
BloC Observer onClose: 11
*/
- BLoc(继承自BlocBase,比Cubit更高级)
使用events而不是暴露的函数来更新状态。
在Bloc内部有一个onEvent方法,通过EventTransformer将event转换为更新状态的方法来刷新状态数据。每个event都可以有对应的 EventHandler来处理该 event,完成后再通过 emit 触发通知状态更新。当状态转变前会调用 onTransition,有当前的状态、触发更新的event、下一个状态。
例:
abstract class CounterEvent {}
class IncrementEvent extends CounterEvent {}
class DecrementEvent extends CounterEvent {}
class CounterBloc extends Bloc<CounterEvent, int> {
CounterBloc(int initialState) : super(initialState) {
on<IncrementEvent>((event, emit) => emit(state + 1));
on<DecrementEvent>((event, emit) => emit(state - 1));
}
@override
void onTransition(Transition<CounterEvent, int> transition) {
print(
'Current: ${transition.currentState}, Next: ${transition.nextState}, Event: ${transition.event}');
super.onTransition(transition);
}
}
void main() {
Bloc.observer = MyBlocObserver();
final counterBloc = CounterBloc(5);
counterBloc.add(IncrementEvent());
counterBloc.add(DecrementEvent());
counterBloc.close();
}
/*
输出如下:
Current: 5, Next: 6, Event: Instance of 'IncrementEvent'
BloC Observer onChange: Change { currentState: 5, nextState: 6 }
Current: 6, Next: 5, Event: Instance of 'DecrementEvent'
BloC Observer onChange: Change { currentState: 6, nextState: 5 }
BloC Observer onClose: 5
*/
- 实现一个简单状态管理类(SimpleBLocProvider)
需要放置在组件树中,因此肯定是Widget。由于内部还需要维护数据,因此继承自StatefulWidget。
需要一个builder属性用来存放原先UI组件的构建,且builder需要携带最新的state状态数据用来更新UI组件。
还需要一个Bloc逻辑组件来获取最新的状态数据。
定义如下:
class SimpleBlocProvider<T> extends StatefulWidget {
// typedef StateBuilder<T> = Widget Function(T state);
final StateBuilder<T> builder;
final BlocBase<T> bloc;
const SimpleBlocProvider(
{Key? key, required this.builder, required this.bloc})
: super(key: key);
@override
_SimpleBlocProviderState<T> createState() => _SimpleBlocProviderState<T>();
}
例:
SimpleBlocProvider<int> (builder: (count) => Text('$count'),)
要实现BLoC刷新,需要监听BLoC状态数据的变化。BLoC 是基于Stream实现的,可以使用Stream的listen方法来监听Stream流数据的变化。
listen方法定义如下:
// 可以在 listen 的 onData 中调用 setState 刷新界面。组件销毁时需要取消监听,在_SimpleBlocProviderState 中定义一个属性_streamSubscription存储 listen 方法的返回值,并在 dispose 中取消监听。
StreamSubscription<T> listen(void onData(T event)?, {Function? onError, void onDone()?, bool? cancelOnError});
例:
_streamSubscription = widget.bloc.stream.listen((data) {
setState(() {
_state = data;
});
});
@override
Widget build(BuildContext context) {
return widget.builder(_state);
}
@override
void dispose() {
_streamSubscription.cancel();
super.dispose();
}
完整代码如下
typedef StateBuilder<T> = Widget Function(T state);
class SimpleBlocProvider<T> extends StatefulWidget {
final StateBuilder<T> builder;
final BlocBase<T> bloc;
const SimpleBlocProvider(
{Key? key, required this.builder, required this.bloc})
: super(key: key);
@override
_SimpleBlocProviderState<T> createState() => _SimpleBlocProviderState<T>();
}
class _SimpleBlocProviderState<T> extends State<SimpleBlocProvider<T>> {
late T _state;
late StreamSubscription<T> _streamSubscription;
@override
void initState() {
_state = widget.bloc.state;
super.initState();
_streamSubscription = widget.bloc.stream.listen((data) {
setState(() {
_state = data;
});
});
}
@override
Widget build(BuildContext context) {
return widget.builder(_state);
}
@override
void dispose() {
_streamSubscription.cancel();
super.dispose();
}
}
==================
使用
class CounterCubit extends Cubit<int> {
CounterCubit({initial = 0}) : super(initial);
void increment() => emit(state + 1);
void decrement() => emit(state - 1);
@override
void onChange(Change<int> change) {
super.onChange(change);
}
}
class SimpleBlocCounterPage extends StatelessWidget {
final counter = CounterCubit();
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('Bloc 计数器'),
),
body: Center(
child: SimpleBlocProvider<int>(
builder: (count) => Text(
'$count',
style: TextStyle(
fontSize: 32,
color: Colors.blue,
),
),
bloc: counter,
),
),
floatingActionButton: FloatingActionButton(
onPressed: () {
counter.increment();
},
tooltip: '点击增加',
child: Icon(Icons.add),
),
);
}
}
===========================
使用2(Bloc)
class Person {
final String name;
final String gender;
const Person({required this.name, required this.gender});
}
abstract class PersonEvent {}
class UsingCnNameEvent extends PersonEvent {}
class UsingEnNameEvent extends PersonEvent {}
class PersonBloc extends Bloc<PersonEvent, Person> {
PersonBloc(Person person) : super(person) {
on<UsingCnNameEvent>(
(event, emit) => emit(Person(name: '狗', gender: '雄性')));
on<UsingEnNameEvent>(
(event, emit) => emit(Person(name: 'Dog', gender: 'male')));
}
}
class SimpleBlocCounterPage extends StatelessWidget {
final personBloc = PersonBloc(Person(name: '狗', gender: '雄性'));
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('Bloc 事件'),
),
body: Center(
child: SimpleBlocProvider<Person>(
builder: (person) => Text(
'姓名:${person.name},性别:${person.gender}',
style: TextStyle(
fontSize: 22,
color: Colors.blue,
),
),
bloc: personBloc,
),
),
floatingActionButton: FloatingActionButton(
onPressed: () {
personBloc.add(UsingEnNameEvent());
},
tooltip: '点击增加',
child: Icon(Icons.add),
),
);
}
}
- BlocProvider
和Provider用法类似,作者为同一人。从Provider迁移到Bloc会很简单。
// 共享状态
final counter = CounterCubit();
BlocProvider.value(
value: counter,
child: SomeWidget(),
);
// 监听状态的部分变化
final isPositive = context.select((CounterBloc b) => b.state >= 0);
// 多状态
MultiBlocProvider(
providers: [
BlocProvider<BlocA>(
create: (BuildContext context) => BlocA(),
),
BlocProvider<BlocB>(
create: (BuildContext context) => BlocB(),
),
BlocProvider<BlocC>(
create: (BuildContext context) => BlocC(),
),
],
child: ChildA(),
)
和Provider的区别
BlocProvider:通过Stream.listen方法监听状态数据改变来更新UI。
Provider:状态对象实现ChangeNotifier接口,并在状态数据改变时调用notifyListeners来通知更新UI。
示例
class BlocCounterWrapper extends StatelessWidget {
@override
Widget build(BuildContext context) {
return BlocProvider(
create: (_) => CounterCubit(),
child: BlocCounterPage(),
);
}
}
class BlocCounterPage extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('Bloc 计数器'),
),
body: Center(
child: BlocBuilder<CounterCubit, int>(
builder: (context, count) => Text(
'$count',
style: TextStyle(
fontSize: 32,
color: Colors.blue,
),
),
),
),
floatingActionButton: FloatingActionButton(
onPressed: () {
context.read<CounterCubit>().increment();
},
tooltip: '点击增加',
child: Icon(Icons.add),
),
);
}
}
- BlocBuilder
// BlocBuilder既可以配合BlocProvider在组件树中使用Bloc对象,也可以单独拥有自己的Bloc对象。
class BlocBuilder<B extends BlocBase<S>, S> extends BlocBuilderBase<B, S> {
const BlocBuilder({
Key? key,
required this.builder,
B? bloc,
// 按条件刷新。返回bool值的回调方法,根据前后状态来决定是否要刷新界面。
// typedef BlocBuilderCondition<S> = bool Function(S previous, S current);
BlocBuilderCondition<S>? buildWhen,
}) : super(key: key, bloc: bloc, buildWhen: buildWhen);
final BlocWidgetBuilder<S> builder;
@override
Widget build(BuildContext context, S state) => builder(context, state);
}
绑定状态对象有两种方式:
1. 没有指定bloc参数时,它会通过BlocProvider和context自动向上寻找匹配的状态对象。这部分代码在其父类BlocBuilderBase(StatefulWidget类型)的State对象中实现,实际上使用的还是context.read来完成的:
@override
void initState() {
super.initState();
_bloc = widget.bloc ?? context.read<B>();
_state = _bloc.state;
}
2. 指定了bloc参数时,则使用指定的bloc对象而无需BlocProvider提供。用法类似GetX的GetBuilder。
示例 (BlocBuilder 按条件刷新)
abstract class PersonalEvent {}
// 获取数据事件
class FetchEvent extends PersonalEvent {}
// 成功事件
class FetchSucessEvent extends PersonalEvent {}
// 失败事件
class FetchFailedEvent extends PersonalEvent {}
enum LoadingStatus {
loading, //加载
success, //加载成功
failed, //加载失败
}
class PersonalResponse {
PersonalEntity? personalProfile;
LoadingStatus status = LoadingStatus.loading;
PersonalResponse({this.personalProfile, required this.status});
}
class PersonalBloc extends Bloc<PersonalEvent, PersonalResponse> {
final String userId;
PersonalEntity? _personalProfile;
PersonalBloc(PersonalResponse initial, {required this.userId})
: super(initial) {
on<FetchEvent>((event, emit) { // 请求网络数据
getPersonalProfile(userId);
});
on<FetchSucessEvent>((event, emit) { // 加载成功后,用请求得到的个人信息对象和加载状态构建新的 PersonalResponse 对象,使用 emit 通知界面刷新。
emit(PersonalResponse(
personalProfile: _personalProfile,
status: LoadingStatus.success,
));
});
on<FetchFailedEvent>((event, emit) { // 加载失败,置空PersonalResponse的个人信息对象,并且标记加载状态为失败。
emit(PersonalResponse(
personalProfile: null,
status: LoadingStatus.failed,
));
});
on<RefreshEvent>((event, emit) {
getPersonalProfile(userId);
});
// 请求数据
add(FetchEvent());
}
void getPersonalProfile(String userId) async {
_personalProfile = await JuejinService().getPersonalProfile(userId);
if (_personalProfile != null) {
add(FetchSucessEvent());
} else {
add(FetchFailedEvent());
}
}
}
class PersonalHomePage extends StatelessWidget {
PersonalHomePage({Key? key}) : super(key: key);
final personalBloc = PersonalBloc(
PersonalResponse(
personalProfile: null,
status: LoadingStatus.loading,
),
userId: '70787819648695');
@override
Widget build(BuildContext context) {
return BlocBuilder<PersonalBloc, PersonalResponse>(
bloc: personalBloc,
builder: (_, personalResponse) {
print('build PersonalHomePage');
if (personalResponse.status == LoadingStatus.loading) {
return Center(
child: Text('加载中...'),
);
}
if (personalResponse.status == LoadingStatus.failed) {
return Center(
child: Text('请求失败'),
);
}
PersonalEntity personalProfile = personalResponse.personalProfile!;
return Stack(
children: [
CustomScrollView(
slivers: [
_getBannerWithAvatar(context, personalProfile),
_getPersonalProfile(personalProfile),
_getPersonalStatistic(personalProfile),
],
),
Positioned(
top: 40,
right: 10,
child: IconButton(
onPressed: () {
personalBloc.add(FetchEvent());
},
icon: Icon(
Icons.refresh,
color: Colors.white,
),
),
),
],
);
},
buildWhen: (previous, next) { // 按条件刷新
if (previous.personalProfile == null || next.personalProfile == null) {
return true;
}
return previous.personalProfile!.userId != next.personalProfile!.userId;
},
);
}
// 其他代码略
}
- BlocListener 状态监听组件
当状态改变后会调用listener参数给定的回调函数(没有返回值),做一些后置处理(显示弹窗提醒或确认、显示状态信息、后置拦截器效果、数据上传、离线存储)。
示例(App退出登录前的二次确认)
// 登录状态(已登陆、已退出、退出确认)
enum LoginStatus { logon, logout, logoutConfirm }
class LoginCubit extends Cubit<LoginStatus> {
LoginCubit({initial = LoginStatus.logout}) : super(initial);
void login() => emit(LoginStatus.logon);
void logout() => emit(LoginStatus.logout);
void logoutConfirm() => emit(LoginStatus.logoutConfirm);
}
按钮和BlocListener都需要使用状态数据,因此使用BlocProvider放置在上层为BlocListener和 BlocBuilder同时提供状态数据。
class BlocListenerWrapper extends StatelessWidget {
@override
Widget build(BuildContext context) {
return BlocProvider(
create: (_) => LoginCubit(),
child: BlocListenerDemo(),
);
}
}
BlocListener部分代码如下:
class BlocListenerDemo extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('BlocListener 示例'),
),
body: Center(
child: BlocListener<LoginCubit, LoginStatus>(
listener: (context, loginSatus) async {
if (loginSatus == LoginStatus.logout ||
loginSatus == LoginStatus.logon) {
ScaffoldMessenger.of(context)
..hideCurrentSnackBar()
..showSnackBar(SnackBar(
content:
Text(loginSatus == LoginStatus.logout ? '已退出登录' : '登录成功'),
duration: Duration(seconds: 1),
));
} else {
var confirmed = await _confirmLogout(context);
if (confirmed == true) {
context.read<LoginCubit>().logout();
}
}
},
child: BlocBuilder<LoginCubit, LoginStatus>(
builder: (context, loginSatus) => TextButton(
child: Text(
loginSatus == LoginStatus.logon ? '退出登录' : '登录',
style: TextStyle(
fontSize: 24.0,
),
),
onPressed: () {
if (loginSatus == LoginStatus.logon) {
context.read<LoginCubit>().logoutConfirm();
} else {
context.read<LoginCubit>().login();
}
},
),
),
),
),
);
}
- BlocConsumer(组合BlocBuilder和BlocListener)
BlocBuilder构建的页面按说不应该是 BlocListener 的子组件,而是同级结构,可使用BlocConsumer来解决。
// 支持构建响应式组件的同时,监听状态变化。
// 支持按条件调用builder刷新组件、按条件调用listener状态监听回调。
const BlocConsumer({
Key? key,
required this.builder, //
required this.listener, // 状态改变后会调用
this.bloc, // 会自动从当前的BuildContext 中查找对应类型的状态对象
this.buildWhen, // 接收前后的状态对象,返回 bool 值,若为 true 才会刷新组件
this.listenWhen, // 接收前后的状态对象,返回 bool 值,若为 true 才会调用listener回调
}) : super(key: key);
看一下BlocConsumer的build方法:
// 基于BlocBuilder实现的,在BlocBuilder的builderWhen中根据listenWhen的返回值来决定是否调用listener回调方法,从而实现了BlocBuilder和BlocListener的聚合。
@override
Widget build(BuildContext context) {
if (widget.bloc == null) context.select<B, int>(identityHashCode);
return BlocBuilder<B, S>(
bloc: _bloc,
builder: widget.builder,
buildWhen: (previous, current) {
if (widget.listenWhen?.call(previous, current) ?? true) {
widget.listener(context, current);
}
return widget.buildWhen?.call(previous, current) ?? true;
},
);
}
- RepositoryProvider(共享状态)
父子组件传值的方式:
1. 构造函数传值
父组件将子组件需要的对象通过构造函数传递给子组件;
如果组件嵌套很深,传递数据对象需要层层传递,将导致代码很难维护。
2. 单例对象
构建单例对象,使得父子组件使用的是同一个对象;
需要自己构建单例类,而实际上要传递的对象可能存在很多个实例。
3. 容器
将对象存入容器中,父子组件使用的时候直接从容器中获取。
如果往容器存储不定数量的实例对象是不合适的。
flutter_bloc插件提供了一种基于组件的依赖注入方式解决这类问题,通过使用 RepositoryProvider,可以为组件树的子组件提供共享对象,这个共享对象只限在组件树中使用,可以通过Provider的方式访问该对象。
RepositoryProvider实际上是Provider的一个子类,通过注册单例的方式实现组件树对象共享,因此其注册的对象会随着Provider的注销而销毁,而且这个对象无需是Bloc子类。因此在无法使用Bloc传输共享对象时,可以使用RepositoryProvider来完成。
看一下RepositoryProvider类的实现:
class RepositoryProvider<T> extends Provider<T>
with RepositoryProviderSingleChildWidget {
RepositoryProvider({
Key? key,
required Create<T> create,
Widget? child,
bool? lazy,
}) : super(
key: key,
create: create,
dispose: (_, __) {},
child: child,
lazy: lazy,
);
RepositoryProvider.value({
Key? key,
required T value,
Widget? child,
}) : super.value(
key: key,
value: value,
child: child,
);
static T of<T>(BuildContext context, {bool listen = false}) {
try {
// RepositoryProvider相比Provider只是将静态方法of的listen参数默认设置为false了,也就是不监听状态对象的变化。
return Provider.of<T>(context, listen: listen);
} on ProviderNotFoundException catch (e) {
if (e.valueType != T) rethrow;
throw FlutterError(
'''
RepositoryProvider.of() called with a context that does not contain a repository of type $T.
No ancestor could be found starting from the context that was passed to RepositoryProvider.of<$T>().
This can happen if the context you used comes from a widget above the RepositoryProvider.
The context used was: $context
''',
);
}
}
}
再看一下RepositoryProviderSingleChildWidget:
// 一个空的Mixin,仅为了方便MultiRepositoryProvider推断RepositoryProvider的类型。
mixin RepositoryProviderSingleChildWidget on SingleChildWidget {}
从上面可以知道,创建对象共享有2种方式:
1. create方式(通过调用一个方法创建新的对象)。
2. value方式(共享一个已有的对象)。
从子组件中访问共享对象(2种方式)
1. 方式1
context.read<T>()
2. 方式2
RepositoryProvider.of<T>(context)
如果有多个对象需要共享,可以使用MultiRepositoryProvider
MultiRepositoryProvider(
providers: [
RepositoryProvider<RepositoryA>(
create: (context) => RepositoryA(),
),
RepositoryProvider<RepositoryB>(
create: (context) => RepositoryB(),
),
RepositoryProvider<RepositoryC>(
create: (context) => RepositoryC(),
),
],
child: ChildA(),
)
实际上 RepositoryProvider 借用Provider 实现了一个组件树上的局部共享对象容器。通过这个容器,为RepositoryProvider的子组件树注入了共享对象,使得子组件可以从 context 中或使用RepositoryProvider.of 静态方法获取共享对象。通过这种方式避免了组件树的层层传值,使得代码更为简洁和易于维护。
RepositoryProvider.value(
child: CustomScrollView(
slivers: [
const BannerWithAvatar(),
const PersonalProfile(),
const PersonalStatistic(),
],
),
value: personalProfile,
),
使用context.read<PersonalEntity>()就可以从 RepositoryProvider 中取出personalProfile对象了
2. GetIt 状态管理(优点:不需要BuildContext)
最初的设计是用于完成依赖注入DI和IOC容器的功能,有点类似JavaSpring的Bean容器。
GetIt容器(全局Map对象):可先往里存入对象,需要时直接取出。容器中的对象是全局的,可用来做数据同步。
注册(存入)
// 存入的对象一般是单例
GetIt.instance.registerSingleton<T>(T object);
// 懒加载方式注册
GetIt.instance.registerLazySingleton<T>(FactoryFunc<T> func)
获取
// 获取容器中的对象
GetIt.instance.get<T>();
依赖库
1. git_it
// 对Flutter的最低SDK版本有要求(如版本7.1.2,需要SDK2.12.x以上版本)
基础的服务管理工具,提供了容器帮助代码找到对应的服务提供对象
2. git_it_mixin
GetIt 的扩展,使得GetIt可以完全应用于状态管理
3. git_it_hooks
GetIt 的扩展,用于flutter_hooks的场景
示例
// dynamic_listener.dart文件
import 'package:home_framework/models/dynamic_entity.dart';
abstract class DynamicListener { // 抽离逻辑需求
// 更新新闻后
void dynamicUpdated(String id, DynamicEntity updatedDynamic);
// 添加新闻后
void dynamicAdded(DynamicEntity newDynamic);
}
// dynamic_page.dart文件
class _DynamicPageState extends State<DynamicPage> implements DynamicListener {
@override
void initState() {
super.initState();
// 注册到GetIt容器。在其他页面可获取_DynamicPageState对象后调用更新或添加方法来更新本页面。
GetIt.instance.registerSingleton<DynamicListener>(this);
}
void dynamicUpdated(String id, DynamicEntity updatedDynamic) { // 更新新闻的具体实现
int index = _listItems.indexWhere((element) => element.id == id);
if (index != -1) {
setState(() {
_listItems[index] = updatedDynamic;
});
}
}
void dynamicAdded(DynamicEntity newDynamic) { // 添加新闻的具体实现
setState(() {
_listItems.insert(0, newDynamic);
});
}
}
// 新增页面
var response = await DynamicService.post(newFormData);
if (response.statusCode == 200) {
Dialogs.showInfo(context, '添加成功');
GetIt.instance
.get<DynamicListener>()
.dynamicAdded(DynamicEntity.fromJson(response.data));
Navigator.of(context).pop();
}
// 编辑页面
if (response.statusCode == 200) {
Dialogs.showInfo(context, '保存成功');
// 处理成功更新后的业务
_handleUpdated(newFormData);
Navigator.of(context).pop();
}
// 处理更新,如果图片更新了才更新动态图片内容
void _handleUpdated(Map<String, String> newFormData) {
_dynamicEntity.title = newFormData['title'];
_dynamicEntity.content = newFormData['content'];
if (newFormData.containsKey('imageUrl')) {
_dynamicEntity.imageUrl = newFormData['imageUrl'];
}
GetIt.instance.get<DynamicListener>().dynamicUpdated(
_dynamicEntity.id,
_dynamicEntity,
);
}
// 详情页面
void _updateViewCount() async {
try {
var response = await DynamicService.updateViewCount(_dynamicEntity.id);
if (response.statusCode == 200) {
setState(() {
_dynamicEntity.viewCount = response.data['viewCount'];
GetIt.instance.get<DynamicListener>().dynamicUpdated(
_dynamicEntity.id,
_dynamicEntity,
);
});
}
} catch (e) {
print(e.toString());
}
}