bounty还有2天到期。回答此问题可获得+50声望奖励。HelloCW正在寻找一个答案从一个有信誉的来源。
我读了关于DI的article。
我尝试使用Hilt的依赖注入来示例化我的Android Compose项目中的每个类,但它让我感到困惑。
1:你知道有些类,如ComponentActivity
,Service
不能被Hilt示例化。
2:虽然一些系统类可以像Code A一样被Hilt示例化,但很难发布。
3:在示例project中,AddEditTaskUiState
的示例是手动创建的,可以看到代码B。
4:在示例project中,CalendarState
的示例是手动创建的,可以看到代码C。
在Android Studio项目中,我应该在哪种情况下使用Hilt的依赖注入?
代码A
@InstallIn(SingletonComponent::class)
@Module
object ProvideModule {
@Provides
@Singleton
fun provideMediaPlayer(): MediaPlayer {
return MediaPlayer()
}
}
字符串
代码B
data class AddEditTaskUiState(
val title: String = "",
...
)
@HiltViewModel
class AddEditTaskViewModel @Inject constructor(
private val taskRepository: TaskRepository,
savedStateHandle: SavedStateHandle
) : ViewModel() {
...
private val _uiState = MutableStateFlow(AddEditTaskUiState())
...
}
型
代码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)
...
}
型
1条答案
按热度按时间vq8itlhq1#
首先,依赖注入的目的是最小化类的紧耦合。为什么?为什么?
1.简化单元测试
1.通过应用第四条原则(即控制反转)和第五条原则(即SOLID的依赖性反转原理)
现在主要有两个问题:
1.我们可以创建哪个类示例来进行注入?可以创建任何示例。如何创建示例?(参见模块、作用域等。在刀柄文档中)。它们可以通过字段注入或构造函数注入来注入。
1.创建后,可以将它们注入到哪些类中?因此,对于Hilt,在Android类中,如这里提到的,以及注入到其他类中的类(例如,如果您的存储库类是viewModel中的注入类,则存储库也可以使用注入的依赖项)。
现在来看具体的课程。您不会在另一个类中插入“活动”或“服务”。不是说你不能,而是你不会/不应该,注射它们是没有意义的。例如,为什么您希望Activity/Service示例位于另一个类中。更实际的是,您应该在Activity中注入viewModel,或者在ViewModel中注入Repository,因为它们必须使用类的示例。或者如您所提到的,是MediaPlayer类的示例(取决于用例)。
那么,现在它如何实现我们的3个目的呢?
1.代码现在是如何可测试的?现在,由于类是松散耦合的,因此类将依赖于由hilt库创建的示例,因此例如,对于单元测试,您可以为SUT类提供一个模拟示例!
1.我们是如何实现控制反转的?示例控制类的行为,而不是类控制示例。因此,通过切换注入的示例,我们可以使用类(就像在测试中,我们注入了模拟示例),从而提高代码的可重用性。
1.我们是如何实现依赖性反转的:通过创建接口,我们可以将它们与Module中的实现类绑定,然后将接口注入到我们所需的类中。例如,在ViewModel中需要一个仓库,因此通过创建一个实现接口的ReposoryImpl类,将接口绑定到Module中的实现类,并将接口(不是实现类)注入ViewModel类,我们的ViewModel(高级模块)不依赖于仓库(低级模块),而是两者都依赖于一个抽象,即接口(因此提高了代码的可重用性,因为接口可以有多个实现,而取决于接口的视图模型可以使用任何实现)