3. 埋点 SDK 初始化与依赖注入:Gradle 配置、Application 初始化、Hilt/手动注入
埋点 SDK 的初始化是数据采集的起点,决定了事件能否正常上报、生命周期是否对齐、模块间是否可解耦。本章围绕 Gradle 依赖声明、Application 启动阶段初始化、依赖注入(Hilt / 手动注入) 三条主线,给出可落地的实现方案与调试要点。
本章目标:
✅ 理解 SDK 初始化时机对埋点质量的影响
✅ 掌握 Gradle 依赖管理与版本统一技巧
✅ 完成 Application 中安全的初始化流程
✅ 使用 Hilt 或手动注入将埋点实例注入到 ViewModel / Compose 层
✅ 理解 SDK 初始化时机对埋点质量的影响
✅ 掌握 Gradle 依赖管理与版本统一技巧
✅ 完成 Application 中安全的初始化流程
✅ 使用 Hilt 或手动注入将埋点实例注入到 ViewModel / Compose 层
3.1 Gradle 依赖配置与版本管理
埋点 SDK(以开源组件 TrackerSDK 为例)需作为 module 级别依赖引入。建议在项目根 build.gradle.kts 统一版本号,避免多 module 冲突。
// 项目级 build.gradle.kts
ext {
set("trackerVersion", "2.1.0")
set("hiltVersion", "2.48")
}
// app/build.gradle.kts
dependencies {
implementation("com.example:tracker-sdk:${rootProject.ext["trackerVersion"]}")
implementation("com.google.dagger:hilt-android:${rootProject.ext["hiltVersion"]}")
kapt("com.google.dagger:hilt-compiler:${rootProject.ext["hiltVersion"]}")
}
| 模块 | 作用 | 典型版本 |
|---|---|---|
| tracker-sdk | 核心埋点库,提供 TrackManager | 2.1.0 |
| tracker-sdk-compose | Compose 扩展(自动采集点击/曝光) | 2.1.0 |
| hilt-android | 依赖注入框架 | 2.48 |
常见错误: 若 Compose 模块与 SDK 版本不匹配,会导致
ComponentActivity 初始化异常。始终通过 ./gradlew app:dependencies 检查冲突。
3.2 Application 初始化埋点 SDK
在 onCreate() 中尽早初始化,但需注意不要阻塞主线程。推荐使用 ContentProvider 启动方式(SDK 内置)或手动调用。
class App : Application() {
override fun onCreate() {
super.onCreate()
// 手动初始化(适用于未使用自动启动的 SDK)
val config = TrackerConfig.Builder()
.appId("com.example.app")
.channel("GooglePlay")
.enableAutoPageTrack(true)
.build()
TrackerManager.init(this, config)
// 注册 Activity 生命周期回调(自动采集页面停留)
registerActivityLifecycleCallbacks(TrackerLifecycleCallbacks())
}
}
调试技巧: 初始化后立即调用
TrackerManager.isInitialized() 确认状态;日志级别在 Debug 时设为 LogLevel.VERBOSE。
3.3 Hilt 注入实现
将 TrackerManager 封装为 Hilt 单例,便于在 ViewModel / UseCase 中直接注入。
// TrackerModule.kt
@Module
@InstallIn(SingletonComponent::class)
object TrackerModule {
@Provides
@Singleton
fun provideTrackerManager(@ApplicationContext context: Context): TrackerManager {
return TrackerManager.getInstance(context)
}
@Provides
@Named("trackerConfig")
fun provideTrackerConfig(): TrackerConfig {
return TrackerConfig.Builder()
.appId("com.example.app")
.channel("GooglePlay")
.enableAutoPageTrack(true)
.build()
}
}
// 在 ViewModel 中使用
@HiltViewModel
class HomeViewModel @Inject constructor(
private val trackerManager: TrackerManager
) : ViewModel() {
fun onButtonClicked(buttonId: String) {
trackerManager.track(
Event("button_click")
.put("button_id", buttonId)
)
}
}
3.4 手动注入(无 Hilt 场景)
在不引入 Dagger/Hilt 的旧项目或小型 Demo 中,通过 Application 单例或 ServiceLocator 模式手动传递。
object TrackerLocator {
private lateinit var trackerManager: TrackerManager
fun init(context: Context) {
val config = TrackerConfig.Builder()
.appId("com.example.app")
.build()
trackerManager = TrackerManager.init(context, config)
}
fun getTracker(): TrackerManager = trackerManager
}
// 初始化
class App : Application() {
override fun onCreate() {
super.onCreate()
TrackerLocator.init(this)
}
}
// ViewModel 中获取
class HomeViewModel : ViewModel() {
private val tracker = TrackerLocator.getTracker()
fun trackEvent() { tracker.track(Event("test")) }
}
稳定性提醒: 手动注入易出现
UninitializedPropertyAccessException。务必在 Application.onCreate() 结束后再访问 TrackerLocator.getTracker()。建议在 ViewModel 的 init 块中调用并捕获异常。
3.5 初始化时序与性能优化
埋点 SDK 初始化通常涉及文件读写、网络配置请求(如动态开关)。建议遵循以下流程:
- 第一阶段(onCreate):加载本地缓存配置 + 创建核心实例(< 10ms)
- 第二阶段(ContentProvider onCreate):如果 SDK 支持自动启动,可在 ContentProvider 中初始化,优先级高于 Application(但需注意 ContentProvider 生命周期)
- 第三阶段(首帧之后):发起远程配置请求、初始化定时上传任务(使用
frameCallback或Handler.postDelayed延迟 500ms)
// 延迟初始化示例(适用于非关键模块)
Handler(Looper.getMainLooper()).postDelayed({
TrackerManager.fetchRemoteConfig()
TrackerManager.startUploadScheduler()
}, 500L)
3.6 本章核心流程图
3.7 常见问题与调试
| 问题 | 原因 | 解决方案 |
|---|---|---|
| 初始化后事件不上报 | SDK 未收到配置或网络权限 | 检查 AndroidManifest.xml 中 INTERNET 权限;打印日志观察配置回调 |
Hilt 注入报 @Inject field cannot be provided | 未在 @Module 提供 Provider | 确认 @Module 被 @InstallIn 声明,并检查 @Provides 方法签名 |
| Compose 组件曝光重复采集 | 同一组件多次注册生命周期 | 使用 DisposableEffect 确保注册与反注册成对出现 |
部署检查清单:
□ Gradle 依赖版本与远程仓库一致
□ Application 中初始化置于
□ Hilt 注入时标注
□ 手动注入时添加
□ Gradle 依赖版本与远程仓库一致
□ Application 中初始化置于
super.onCreate() 之后□ Hilt 注入时标注
@Singleton 避免内存泄漏□ 手动注入时添加
lateinit 判空保护