Flutter 整洁架构下如何处理Crashlytics异常上报?
Crashlytics 异常上报的架构设计建议
首先明确:Crashlytics绝对不能作为数据源,它是错误追踪工具,属于跨领域的辅助能力,和数据源(负责数据读写)的职责完全不搭边。正确的做法是像你提到的网络检查模块那样,做成独立的可注入模块,传入RepositoryImpl。
为什么要做成独立模块?
- 单一职责原则:Repository的核心职责是处理数据的获取、转换和分发,错误上报是独立的监控职责,拆分后每个模块的职责更清晰,代码更易维护。
- 解耦与可测试性:如果在Repository里硬编码Crashlytics调用,单元测试时必须依赖真实的Crashlytics SDK,无法隔离测试逻辑。做成接口+实现的形式后,测试时可以传入一个空实现或模拟实现,完全不影响Repository的业务逻辑测试。
- 扩展性:以后如果要替换错误上报工具(比如换成内部监控系统、Sentry等),只需要新增一个
ErrorReporter接口的实现类,不用修改所有Repository里的上报代码,符合开闭原则。
具体实现示例
- 定义错误上报接口,抽象上报能力:
interface ErrorReporter { // 支持携带上下文信息,方便定位问题 fun reportException(throwable: Throwable, context: Map<String, String>? = null) }
- 实现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) } }
- 在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
相关产品推荐
相关产品推荐

