• Flutter如何做登出提示功能?
  • 发布于 2个月前
  • 374 热度
    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 部分的代码如下:
// 堆代码 duidaima.com
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 退出登录。效果如下:


总结
可以看到,有了BlocListener,我们可以实现类似后置拦截器的效果,在状态改变后做一些额外的的处理,比如提示信息,或者是做数据的上传、离线存储等。通过这种方式处理,可以降低业务代码的耦合度。
用户评论