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

如何在Jetpack Compose中使用纯Dagger 2实现依赖注入?

在Jetpack Compose中使用纯Dagger 2实现依赖注入

核心思路是通过CompositionLocal将Dagger组件传递到Compose树中,再封装Composable工具函数暴露依赖,以下是完整实现方案:

1. 定义Dagger组件与依赖模块

和常规Dagger用法一致,先编写提供依赖的模块和组件接口。示例中我们注入一个UserRepository:

// 业务依赖类
class UserRepository(private val apiService: ApiService) {
    suspend fun fetchCurrentUser(): User = apiService.getUser()
}

// Dagger模块:提供基础依赖
@Module
class AppModule {
    @Provides
    fun provideApiService(): ApiService {
        return Retrofit.Builder()
            .baseUrl("https://example.com/")
            .addConverterFactory(GsonConverterFactory.create())
            .build()
            .create(ApiService::class.java)
    }

    @Provides
    fun provideUserRepository(apiService: ApiService): UserRepository {
        return UserRepository(apiService)
    }
}

// Dagger根组件:暴露需要注入的依赖
@Component(modules = [AppModule::class])
interface AppComponent {
    fun userRepository(): UserRepository
}

2. 创建CompositionLocal持有Dagger组件

Compose中用CompositionLocal在组件树中传递依赖,这里定义全局CompositionLocal持有AppComponent:

// 定义CompositionLocal,默认值设为error确保必须在Provider范围内使用
val LocalAppComponent = staticCompositionLocalOf<AppComponent> {
    error("AppComponent未在CompositionLocalProvider中提供")
}

3. 在应用入口注入CompositionLocal

在启动Compose的Activity中初始化Dagger组件,并用CompositionLocalProvider将其提供给整个Compose树:

class MainActivity : ComponentActivity() {
    private lateinit var appComponent: AppComponent

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        // 初始化Dagger根组件
        appComponent = DaggerAppComponent.create()

        setContent {
            // 传递AppComponent到整个Compose树
            CompositionLocalProvider(LocalAppComponent provides appComponent) {
                MyApp()
            }
        }
    }
}

4. 封装Composable工具函数获取依赖

为简化UI层调用,封装Composable函数直接返回所需依赖:

@Composable
fun userRepository(): UserRepository {
    return LocalAppComponent.current.userRepository()
}

5. 在Composable中使用依赖

任意子Composable都可直接调用工具函数获取依赖:

@Composable
fun UserProfileScreen() {
    val repo = userRepository()
    val userState = remember { mutableStateOf<User?>(null) }

    LaunchedEffect(Unit) {
        userState.value = repo.fetchCurrentUser()
    }

    userState.value?.let { user ->
        Column(modifier = Modifier.padding(16.dp)) {
            Text(text = "用户名:${user.name}")
            Text(text = "邮箱:${user.email}")
        }
    } ?: Text(text = "加载中...")
}

进阶:屏幕级子组件注入

如果需要针对特定屏幕使用独立的Dagger子组件,可嵌套CompositionLocalProvider:

  1. 定义子组件与工厂:
@Subcomponent(modules = [ProfileModule::class])
interface ProfileComponent {
    fun profileViewModel(): ProfileViewModel

    @Subcomponent.Factory
    interface Factory {
        fun create(): ProfileComponent
    }
}

// 在根组件中添加子组件工厂
@Component(modules = [AppModule::class])
interface AppComponent {
    fun profileComponentFactory(): ProfileComponent.Factory
}
  1. 在屏幕Composable中提供子组件:
val LocalProfileComponent = staticCompositionLocalOf<ProfileComponent> {
    error("ProfileComponent未提供")
}

@Composable
fun profileViewModel(): ProfileViewModel {
    return LocalProfileComponent.current.profileViewModel()
}

@Composable
fun ProfileScreen() {
    val appComponent = LocalAppComponent.current
    // 用remember缓存子组件,避免重组时重复创建
    val profileComponent = remember {
        appComponent.profileComponentFactory().create()
    }

    CompositionLocalProvider(LocalProfileComponent provides profileComponent) {
        val viewModel = profileViewModel()
        // 渲染UI逻辑
    }
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.10 17:52:24