如何在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:
- 定义子组件与工厂:
@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 }
- 在屏幕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
相关产品推荐
相关产品推荐

