Android Studio项目中,何时适合使用Hilt进行依赖注入?
我已经阅读了关于依赖注入(DI)的官方文章,尝试在Android Compose项目中用Hilt实例化所有类,但遇到了几个困惑:
- 像
ComponentActivity、Service这类系统组件无法通过Hilt实例化; - 虽然可以像Code A那样用Hilt实例化部分系统类,但很难正确释放;
- 在官方示例项目中,
AddEditTaskUiState是手动创建的(见Code B); - 在另一个官方示例项目中,
CalendarState也是手动创建的(见Code C)。
Code A
@InstallIn(SingletonComponent::class) @Module object ProvideModule { @Provides @Singleton fun provideMediaPlayer(): MediaPlayer { return MediaPlayer() } }
Code B
data class AddEditTaskUiState( val title: String = "", ... ) @HiltViewModel class AddEditTaskViewModel @Inject constructor( private val taskRepository: TaskRepository, savedStateHandle: SavedStateHandle ) : ViewModel() { ... private val _uiState = MutableStateFlow(AddEditTaskUiState()) ... }
Code C
@HiltViewModel class MainViewModel @Inject constructor( private val destinationsRepository: DestinationsRepository, @DefaultDispatcher private val defaultDispatcher: CoroutineDispatcher ) : ViewModel() { val calendarState = CalendarState() ... } class CalendarState { val calendarUiState = mutableStateOf(CalendarUiState()) val listMonths: List<Month> private val calendarStartDate: LocalDate = LocalDate.now() .withMonth(1).withDayOfMonth(1) ... }
何时使用Hilt进行依赖注入
跨组件/模块共享的依赖:当某个类需要在多个ViewModel、Repository或其他组件中复用,且需要保证单一实例(比如网络请求的Retrofit实例、数据库Dao、全局配置类),用Hilt的单例或对应作用域注解管理,能避免重复创建实例,统一生命周期。
依赖链复杂的类:如果一个类依赖多个其他类(比如ViewModel依赖Repository,Repository依赖Dao和网络服务),用Hilt自动注入可以省去手动创建嵌套实例的繁琐,同时让依赖关系更清晰。
需要跟随Android组件生命周期的依赖:Hilt提供了对应Android组件的作用域(比如
ActivityRetainedComponent、ViewModelComponent),当你需要依赖的生命周期和Activity、ViewModel绑定的时候,用Hilt可以自动在组件销毁时释放依赖,避免内存泄漏。比如ViewModel用@HiltViewModel注解,Hilt会自动处理其生命周期。测试需要替换依赖的场景:如果后续需要做单元测试,用Hilt注入的依赖可以轻松替换为Mock实现,不用修改业务代码。比如Repository可以在测试模块中提供Mock版本,Hilt会自动注入测试用实例。
不需要使用Hilt的场景
系统组件类:
ComponentActivity、Service、BroadcastReceiver这些是Android系统负责实例化的组件,Hilt无法接管它们的创建,只能通过@AndroidEntryPoint注解让Hilt注入它们内部的依赖,而不是实例化组件本身。简单的、无依赖的数据类/状态类:比如
AddEditTaskUiState这种纯数据载体,没有依赖其他类,手动创建更简单,不需要注入。同理CalendarState这类只和ViewModel绑定、没有外部依赖的状态类,直接在ViewModel中实例化更直观,没必要用Hilt。生命周期极短、不需要共享的局部实例:比如某个函数内部临时创建的工具类实例,用完就销毁,手动创建更高效,不需要通过Hilt管理。
难以管理生命周期的系统类:像
MediaPlayer这类需要手动调用release()的系统类,Hilt的单例作用域会让它一直存活到APP进程结束,容易导致内存泄漏,这种情况更适合在使用它的组件内部创建并手动管理释放,或者用自定义作用域绑定到组件生命周期(比如Activity作用域),确保组件销毁时释放。
内容的提问来源于stack exchange,提问作者HelloCW

