Dependency Injection Mastery
SKILL.md
Dependency Injection Mastery (依赖注入专精)
Instructions
- 确认问题属于 DI 架构或 Scope 设计
- 依照下方章节顺序套用
- 一次只调整一种注入模式或 module
- 完成后对照 Quick Checklist
When to Use
- Scenario A:新项目 DI 架构创建
- Scenario C:旧项目现代化与模块拆分
- Scenario F:KMP 共用模块的 DI 调整
Example Prompts
- "请参考 Assisted Injection,替 ViewModel 加入动态参数"
- "依照 Custom Hilt Components 创建 User Session Scope"
- "请用 Multi-binding 章节设计插件式支付模块"
Workflow
- 先确认 Assisted Injection 与 Scope 需求
- 再整理 Module Organization 与 Qualifier
- 最后用 Quick Checklist 验收
Practical Notes (2026)
- 多模块采 API/impl 分离,避免跨模块直接依赖实作
- 跨模块导航与 Service 以 interface + EntryPoint 统一
- Scope 设计先画出生命周期,再落地到 Module
Minimal Template
目标:
Scope:
Module 结构:
注入模式:
验收: Quick Checklist
Assisted Injection
当 ViewModel 或 Worker 需要同时接收 DI 的依赖与 Runtime 参数时使用。
ViewModel with SavedStateHandle + Custom Args
@HiltViewModel(assistedFactory = DetailViewModel.Factory::class)
class DetailViewModel @AssistedInject constructor(
@Assisted private val productId: String,
@Assisted savedStateHandle: SavedStateHandle,
private val repository: ProductRepository
) : ViewModel() {
@AssistedFactory
interface Factory {
fun create(productId: String, savedStateHandle: SavedStateHandle): DetailViewModel
}
}
// 在 Compose 中使用
@Composable
fun DetailScreen(productId: String) {
val viewModel = hiltViewModel<DetailViewModel, DetailViewModel.Factory> { factory ->
factory.create(productId, createSavedStateHandle())
}
}
WorkManager with Assisted Injection
@HiltWorker
class SyncWorker @AssistedInject constructor(
@Assisted context: Context,
@Assisted params: WorkerParameters,
private val repository: Repository
) : CoroutineWorker(context, params) {
override suspend fun doWork(): Result {
repository.sync()
return Result.success()
}
}
Custom Hilt Components (Scopes)
创建自定义的生命周期范围,例如 User Session。
定义 Custom Scope
@Scope
@Retention(AnnotationRetention.RUNTIME)
annotation class UserSessionScope
@DefineComponent(parent = SingletonComponent::class)
@UserSessionScope
interface UserSessionComponent
@DefineComponent.Builder
interface UserSessionComponentBuilder {
fun setUser(@BindsInstance user: User): UserSessionComponentBuilder
fun build(): UserSessionComponent
}
管理 Component 生命周期
@EntryPoint
@InstallIn(UserSessionComponent::class)
interface UserSessionEntryPoint {
fun paymentService(): PaymentService
}
@Singleton
class UserSessionManager @Inject constructor(
private val componentBuilder: Provider<UserSessionComponentBuilder>
) {
private var component: UserSessionComponent? = null
fun login(user: User) {
component = componentBuilder.get().setUser(user).build()
}
fun logout() {
component = null
}
fun getPaymentService(): PaymentService {
val currentComponent = checkNotNull(component) { "User not logged in" }
return EntryPoints.get(currentComponent, UserSessionEntryPoint::class.java)
.paymentService()
}
}
Multi-binding (Set & Map)
实作 Plugin 架构,例如多种支付方式。
Set Multibinding
interface PaymentProcessor {
fun process(amount: Double): Result
}
@Module
@InstallIn(SingletonComponent::class)
abstract class PaymentModule {
@Binds
@IntoSet
abstract fun bindCreditCard(impl: CreditCardProcessor): PaymentProcessor
@Binds
@IntoSet
abstract fun bindPayPal(impl: PayPalProcessor): PaymentProcessor
}
// 注入所有实作
class PaymentService @Inject constructor(
private val processors: Set<@JvmSuppressWildcards PaymentProcessor>
) {
fun processAll(amount: Double) {
processors.forEach { it.process(amount) }
}
}
Map Multibinding (with Key)
enum class PaymentType { CREDIT_CARD, PAYPAL, GOOGLE_PAY }
@MapKey
annotation class PaymentTypeKey(val value: PaymentType)
@Module
@InstallIn(SingletonComponent::class)
abstract class PaymentModule {
@Binds
@IntoMap
@PaymentTypeKey(PaymentType.CREDIT_CARD)
abstract fun bindCreditCard(impl: CreditCardProcessor): PaymentProcessor
}
// 按 Key 取得特定实作
class PaymentService @Inject constructor(
private val processors: Map<PaymentType, @JvmSuppressWildcards PaymentProcessor>
) {
fun process(type: PaymentType, amount: Double) {
processors[type]?.process(amount)
}
}
Module Organization
分层架构
di/
├── AppModule.kt # Application-level
├── NetworkModule.kt # Retrofit, OkHttp
├── DatabaseModule.kt # Room
├── RepositoryModule.kt # Repository bindings
└── UseCaseModule.kt # UseCase bindings
Qualifier 使用
@Qualifier
@Retention(AnnotationRetention.BINARY)
annotation class IoDispatcher
@Module
@InstallIn(SingletonComponent::class)
object DispatcherModule {
@Provides
@IoDispatcher
fun provideIoDispatcher(): CoroutineDispatcher = Dispatchers.IO
}
Quick Checklist
- ViewModel 动态参数使用 Assisted Injection
- 避免在 Module 中使用
@Provides创建复杂逻辑 - Qualifier 用于区分相同类型的不同实例
- 避免 Circular Dependencies
- 测试时使用
@UninstallModules+@TestInstallIn