如何在纯Kotlin模块中隔离Firebase Analytics依赖
这个问题我之前也碰到过,Firebase Analytics的很多核心API确实是绑定Android平台的,直接在纯Kotlin/JVM模块里引入相关依赖肯定会碰到找不到类的问题。不过我们可以通过依赖倒置+接口抽象的思路,把平台相关的实现和纯Kotlin的核心逻辑彻底分开,既满足你现在复用的需求,也为以后迁移到KMP打下基础。具体做法如下:
1. 在纯Kotlin模块中定义抽象接口与核心逻辑
首先,我们要把所有和Firebase直接相关的代码从纯Kotlin模块里移除,换成自己定义的抽象接口。这样纯Kotlin模块只负责业务逻辑,完全不依赖任何Android或Firebase库。
比如创建一个AnalyticsService接口,以及基于这个接口的业务扩展函数:
// 纯Kotlin模块的代码 interface AnalyticsService { // 定义通用的日志方法,参数用平台无关的类型 fun logEvent(eventName: String, params: Map<String, Any>) } // 你的业务扩展函数,基于抽象接口实现,不再依赖Firebase的ParametersBuilder fun AnalyticsService.logSuccessEvent(isSuccess: Boolean) { logEvent( eventName = "operation_completed", params = mapOf("success" to if (isSuccess) 1 else 0) ) }
这样一来,纯Kotlin模块的代码完全是平台无关的,既不会碰到找不到Android类的问题,以后迁移到KMP时也能直接复用。
2. 在Android模块中实现Firebase具体逻辑
接下来,把Firebase相关的实现放到Android专属模块里,让它依赖纯Kotlin模块并实现AnalyticsService接口:
// Android模块的代码 import com.google.firebase.analytics.FirebaseAnalytics import android.os.Bundle class FirebaseAnalyticsServiceImpl( private val firebaseAnalytics: FirebaseAnalytics ) : AnalyticsService { override fun logEvent(eventName: String, params: Map<String, Any>) { // 把纯Kotlin的Map参数转换成Firebase需要的Bundle val bundle = Bundle().apply { params.forEach { (key, value) -> when (value) { is String -> putString(key, value) is Int -> putInt(key, value) is Long -> putLong(key, value) is Float -> putFloat(key, value) // 根据你的需求添加更多类型支持 } } } firebaseAnalytics.logEvent(eventName, bundle) } }
3. 调整Gradle依赖配置
- 纯Kotlin模块:只保留
kotlin-jvm插件,移除所有Firebase和Android相关依赖:
// 纯Kotlin模块的build.gradle.kts plugins { alias(libs.plugins.kotlinJvm) } dependencies { // 只添加纯Kotlin依赖,比如kotlin-stdlib等 implementation(libs.kotlin.stdlib) }
- Android模块:保留Firebase依赖,并添加对纯Kotlin模块的依赖:
// Android模块的build.gradle.kts plugins { id("com.android.library") alias(libs.plugins.kotlinAndroid) id("com.google.gms.google-services") // 别忘了Firebase需要的插件 } dependencies { // 依赖纯Kotlin模块 implementation(project(":your-kotlin-analytics-module")) // Firebase相关依赖保留在这里 api(platform(libs.firebaseBom)) api(libs.firebaseAnalytics) }
4. 业务层使用方式
在你的业务代码中,只需要依赖纯Kotlin模块的AnalyticsService接口,具体的实现由Android模块提供(比如通过依赖注入框架注入FirebaseAnalyticsServiceImpl)。这样业务代码完全感知不到Firebase的存在,也能轻松切换其他分析平台。
为什么这种方式可行?
核心思路是依赖倒置原则:让纯Kotlin模块依赖抽象接口,而不是具体的平台实现;平台相关的代码(比如Firebase)依赖纯Kotlin模块并实现接口。这样既隔离了平台依赖,又保证了业务逻辑的复用性,以后如果要迁移到KMP,只需要在iOS等其他平台实现AnalyticsService接口即可,纯Kotlin的业务逻辑完全不用改。
内容来源于stack exchange

