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

Flutter 整洁架构下如何处理Crashlytics异常上报?

Crashlytics 异常上报的架构设计建议

首先明确:Crashlytics绝对不能作为数据源,它是错误追踪工具,属于跨领域的辅助能力,和数据源(负责数据读写)的职责完全不搭边。正确的做法是像你提到的网络检查模块那样,做成独立的可注入模块,传入RepositoryImpl。

为什么要做成独立模块?

  • 单一职责原则:Repository的核心职责是处理数据的获取、转换和分发,错误上报是独立的监控职责,拆分后每个模块的职责更清晰,代码更易维护。
  • 解耦与可测试性:如果在Repository里硬编码Crashlytics调用,单元测试时必须依赖真实的Crashlytics SDK,无法隔离测试逻辑。做成接口+实现的形式后,测试时可以传入一个空实现或模拟实现,完全不影响Repository的业务逻辑测试。
  • 扩展性:以后如果要替换错误上报工具(比如换成内部监控系统、Sentry等),只需要新增一个ErrorReporter接口的实现类,不用修改所有Repository里的上报代码,符合开闭原则。

具体实现示例

  1. 定义错误上报接口,抽象上报能力:
interface ErrorReporter {
    // 支持携带上下文信息,方便定位问题
    fun reportException(throwable: Throwable, context: Map<String, String>? = null)
}
  1. 实现Crashlytics版本的上报器:
class CrashlyticsErrorReporter : ErrorReporter {
    override fun reportException(throwable: Throwable, context: Map<String, String>? = null) {
        // 可选:添加自定义上下文,比如用户ID、请求参数等
        context?.forEach { (key, value) ->
            FirebaseCrashlytics.getInstance().setCustomKey(key, value)
        }
        FirebaseCrashlytics.getInstance().recordException(throwable)
    }
}
  1. 在RepositoryImpl中注入该接口,在catch块中调用:
class UserRepositoryImpl(
    private val userRemoteDataSource: UserRemoteDataSource,
    private val errorReporter: ErrorReporter // 注入上报器
) : UserRepository {

    override suspend fun getUser(userId: String): Result<User> {
        return try {
            val user = userRemoteDataSource.fetchUser(userId)
            Result.success(user)
        } catch (e: Exception) {
            // 上报异常,带上当前请求的用户ID作为上下文
            errorReporter.reportException(e, mapOf("userId" to userId))
            Result.failure(e)
        }
    }
}

额外补充

如果是全局未捕获的异常(比如UI线程的崩溃),建议在Application类中注册全局异常处理器,配合Crashlytics使用,这样能覆盖所有未被catch的异常:

class MyApp : Application() {
    override fun onCreate() {
        super.onCreate()
        val defaultHandler = Thread.getDefaultUncaughtExceptionHandler()
        Thread.setDefaultUncaughtExceptionHandler { thread, throwable ->
            FirebaseCrashlytics.getInstance().recordException(throwable)
            defaultHandler?.uncaughtException(thread, throwable)
        }
    }
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.24 16:32:36