You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何仅在请求耗时超过200ms时弹出Dialog?

实现延迟显示的注销加载Dialog

你可以通过定时器+异步请求监听的方式实现需求,核心逻辑是:启动200ms定时器,若请求超时未完成则显示Dialog;请求完成后(无论成功/失败),立即取消定时器、关闭已显示的Dialog,最后跳转登录页。

下面提供两种适配你技术栈的实现方案:

方案一:结合Bloc状态监听(适配现有代码)

假设你的AuthBloc会在注销请求完成时发出LogoutSuccess或LogoutFailure状态,修改点击事件逻辑如下:

onTap: () {
  final authBloc = context.read<AuthBloc>();
  Timer? loadingTimer;
  BuildContext? dialogContext;
  StreamSubscription? stateSubscription;

  // 启动200ms定时器,超时则显示加载Dialog
  loadingTimer = Timer(const Duration(milliseconds: 200), () {
    showDialog(
      context: context,
      barrierDismissible: false, // 禁止手动关闭
      builder: (ctx) {
        dialogContext = ctx;
        return const AlertDialog(
          content: Row(
            children: [
              CircularProgressIndicator(),
              SizedBox(width: 16),
              Text("正在注销..."),
            ],
          ),
        );
      },
    );
  });

  // 监听Bloc状态,处理请求完成后的逻辑
  stateSubscription = authBloc.stream.listen((state) {
    if (state is LogoutSuccess || state is LogoutFailure) {
      // 取消定时器,避免Dialog后续弹出
      loadingTimer?.cancel();
      // 关闭已显示的Dialog
      if (dialogContext != null) {
        Navigator.of(dialogContext!).pop();
      }
      // 跳转登录页
      Navigator.of(context).push(MaterialPageRoute(builder: (context) => const LoginPage()));
      // 取消状态订阅,防止内存泄漏
      stateSubscription?.cancel();
    }
  });

  // 发起注销请求
  authBloc.add(LogoutRequested());
},

同时确保AuthBloc中LogoutRequested事件的处理为异步,并发出对应状态:

class AuthBloc extends Bloc<AuthEvent, AuthState> {
  final Dio dio;

  AuthBloc(this.dio) : super(AuthInitial()) {
    on<LogoutRequested>((event, emit) async {
      try {
        // 执行Dio注销请求
        await dio.post('/logout');
        emit(LogoutSuccess());
      } catch (e) {
        emit(LogoutFailure(error: e.toString()));
      }
    });
  }
}

方案二:直接在点击事件中处理Dio请求(更轻量)

若不想依赖Bloc状态,可直接在点击事件中调用Dio接口,逻辑更直观:

onTap: () async {
  Timer? loadingTimer;
  BuildContext? dialogContext;

  // 启动200ms延迟定时器
  loadingTimer = Timer(const Duration(milliseconds: 200), () {
    showDialog(
      context: context,
      barrierDismissible: false,
      builder: (ctx) {
        dialogContext = ctx;
        return const AlertDialog(
          content: Row(
            children: [
              CircularProgressIndicator(),
              SizedBox(width: 16),
              Text("正在注销..."),
            ],
          ),
        );
      },
    );
  });

  try {
    // 执行Dio注销请求
    await dio.post('/logout');
  } catch (e) {
    // 可在此添加错误提示,比如SnackBar
    // ScaffoldMessenger.of(context).showSnackBar(SnackBar(content: Text("注销失败: $e")));
  } finally {
    // 请求完成后,无论成功失败都清理资源
    loadingTimer?.cancel();
    if (dialogContext != null) {
      Navigator.of(dialogContext!).pop();
    }
    // 跳转登录页
    Navigator.of(context).push(MaterialPageRoute(builder: (context) => const LoginPage()));
  }
},

关键注意事项

  • 定时器清理:请求完成后必须取消定时器,避免请求快速完成后Dialog仍弹出
  • Dialog关闭:保存Dialog的上下文用于后续关闭,因为showDialog会创建新的上下文
  • 内存泄漏防范:Bloc状态订阅要及时取消,避免组件销毁后仍存在监听
  • 用户体验:设置barrierDismissible: false防止用户在注销过程中手动关闭Dialog

内容的提问来源于stack exchange,提问作者Karol Wiśniewski

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.25 15:33:17