退出操作二次确认怎么做代码才更优雅 —— BLoC轻松解决
2022-04-05 本文已影响0人
岛上码农
前言
在 flutter_bloc提供了一个状态监听组件 BlocListener
,当状态发生改变时会调用listener
参数给定的回调函数,这个方法没有返回值,可以用于我们处理一些提醒,例如显示弹窗提醒或确认,显示状态信息等等。有了 BlocListener
,相当于给我们提供了一个额外处理对象变化的入口。接下来我们通过BlocListener
实现某些 App退出登录前的二次确认。
登录状态
为了简化逻辑,我们的登录数据只有一个枚举 LoginStatus
,有三个状态:
- logon:已登录
- logout:已退出登录
- logoutConfirm:退出登录确认
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();
}
},
),
),
),
),
);
}
当状态是已登录和已退出登录时显示一个 SnackBar
提示结果,而如果是确认登录,则弹出一个对话框。对话框会返回 true
或 false
,如果是 true
则表示确认退出,此时再调用 LoginCubit
的 logout
退出登录。源码已提交至:BLoC状态管理源码,运行效果如下:
总结
可以看到,有了BlocListener
,我们可以实现类似后置拦截器的效果,在状态改变后做一些额外的的处理,比如提示信息,或者是做数据的上传、离线存储等。通过这种方式处理,可以降低业务代码的耦合度。