Android开发Flutter圈子Flutter 入门与实战

退出操作二次确认怎么做代码才更优雅 —— BLoC轻松解决

2022-04-05  本文已影响0人  岛上码农

前言

在 flutter_bloc提供了一个状态监听组件 BlocListener,当状态发生改变时会调用listener参数给定的回调函数,这个方法没有返回值,可以用于我们处理一些提醒,例如显示弹窗提醒或确认,显示状态信息等等。有了 BlocListener,相当于给我们提供了一个额外处理对象变化的入口。接下来我们通过BlocListener实现某些 App退出登录前的二次确认。

登录状态

为了简化逻辑,我们的登录数据只有一个枚举 LoginStatus,有三个状态:


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 放置在上层为 BlocListenerBlocBuilder 同时提供状态数据。

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 提示结果,而如果是确认登录,则弹出一个对话框。对话框会返回 truefalse,如果是 true 则表示确认退出,此时再调用 LoginCubitlogout 退出登录。源码已提交至:BLoC状态管理源码,运行效果如下:

运行效果

总结

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

上一篇下一篇

猜你喜欢

热点阅读