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

Flutter FutureBuilder异常如何添加通用默认处理行为?

异常无法捕获的原因

FutureBuilder内部已经实现了对传入Future的异常捕获逻辑,所有异常会被封装到AsyncSnapshot.error属性中,不会向上抛到Flutter框架层或者Zone环境,因此你配置的全局异常捕获回调无法接收到这部分异常。

低冗余解决方案:封装通用自定义FutureBuilder

直接封装一层自定义的FutureBuilder组件,内置默认的加载态、错误处理、异常上报逻辑,业务层直接调用封装后的组件即可,无需每个页面重复写判断逻辑。

封装代码示例

import 'package:flutter/material.dart';
import 'package:firebase_crashlytics/firebase_crashlytics.dart';

typedef AsyncSuccessBuilder<T> = Widget Function(
  BuildContext context,
  T data,
);

class CommonFutureBuilder<T> extends StatelessWidget {
  final Future<T> future;
  final AsyncSuccessBuilder<T> onSuccess;
  final Widget Function(Object error, StackTrace stackTrace)? onError;
  final Widget? onLoading;

  const CommonFutureBuilder({
    super.key,
    required this.future,
    required this.onSuccess,
    this.onError,
    this.onLoading,
  });

  @override
  Widget build(BuildContext context) {
    return FutureBuilder<T>(
      future: future,
      builder: (context, snapshot) {
        // 加载状态走全局默认逻辑,支持自定义覆盖
        if (snapshot.connectionState == ConnectionState.waiting) {
          return onLoading ?? const Center(child: CircularProgressIndicator());
        }
        // 错误状态统一上报+全局默认处理,支持自定义覆盖
        if (snapshot.hasError) {
          final error = snapshot.error!;
          final stackTrace = snapshot.stackTrace!;
          // 全局统一上报错误到Crashlytics,无需业务层重复处理
          FirebaseCrashlytics.instance.recordError(error, stackTrace);
          return onError?.call(error, stackTrace) ?? _defaultErrorWidget(error);
        }
        // 成功状态返回业务自定义内容
        return onSuccess(context, snapshot.data as T);
      },
    );
  }

  // 全局通用默认错误视图
  Widget _defaultErrorWidget(Object error) {
    return Center(
      child: Column(
        mainAxisSize: MainAxisSize.min,
        children: [
          const Icon(Icons.error_outline, color: Colors.red, size: 48),
          const SizedBox(height: 16),
          Text('加载失败:${error.toString()}'),
        ],
      ),
    );
  }
}

业务层使用方式

无需重复处理加载、错误、上报逻辑,仅在需要自定义特殊样式时额外传参即可:

// 常规场景,直接走全局默认逻辑
CommonFutureBuilder<String>(
  future: loadServerData(),
  onSuccess: (context, data) {
    return Text(data);
  },
)

// 需要自定义样式的特殊场景,单独传参覆盖默认逻辑
CommonFutureBuilder<String>(
  future: loadServerData(),
  onSuccess: (context, data) => Text(data),
  onError: (error, stackTrace) => CustomErrorPage(error),
  onLoading: CustomLoadingAnimation(),
)

注意:传入的future需要提前在initState等生命周期中初始化,不要直接在build方法中创建,否则组件每次重绘都会重新触发Future请求。

内容的提问来源于stack exchange,提问作者alexlipa

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.05 11:27:03