使用 HILT 提供领域层 UseCase 类

CJR*_*CJR 3 android kotlin dagger-2 android-jetpack dagger-hilt

我正在将Google I/O 的应用程序中的一些架构设计实现到我自己的应用程序中,但我在他们的应用程序中遇到了一些让我感到困惑的东西。

它们有一个带有存储库用例的域层,我通常在我的应用程序中使用它。但是,我确实必须在我的应用程序中为这些用例提供 dagger。但在 Google 的 I/O 应用程序上,我找不到任何提供这些用例的模块。当与注释 @HiltViewModel 的视图模型一起使用时(在我自己的应用程序中),它似乎有效?不知何故,这些被注入到我的视图模型中。我确实必须使用 Hilt 提供所有用例的依赖项(存储库等),但我不必通过 Hilt 提供任何用例。

这是它在我的代码中的外观示例。

用例:

abstract class UseCase<in P, R>(private val coroutineDispatcher: CoroutineDispatcher) {

    suspend operator fun invoke(parameters: P): Resource<R> {
        return try {
            withContext(coroutineDispatcher) {
                execute(parameters).let {
                    Resource.Success(it)
                }
            }
        } catch (e: Exception) {
            Timber.d(e)
            Resource.Error(e.toString())
        }
    }

    @Throws(RuntimeException::class)
    protected abstract suspend fun execute(parameters: P): R
}
Run Code Online (Sandbox Code Playgroud)

usecase的具体实现:

class GetListUseCase @Inject constructor(
    private val coroutineDispatcher: CoroutineDispatcher,
    private val remoteRepository: RemoteRepository
): UseCase<ListRequest,ItemsList>(coroutineDispatcher) {

    override suspend fun execute(parameters: ListRequest): ItemsList{
        return remoteRepository.getList(parameters)
    }

}
Run Code Online (Sandbox Code Playgroud)

视图模型:

@HiltViewModel
class DetailViewModel @Inject constructor(
    private val GetListUseCase: getListUseCase
): ViewModel() {

    suspend fun getList(): Resource<ItemsList> {
        getPokemonListUseCase.invoke(ListRequest(3))
    }

}
Run Code Online (Sandbox Code Playgroud)

提供的存储库示例:

@Singleton
@Provides
fun provideRemoteRepository(
    api: Api
): RemoteRepository = RemoteRepositoryImpl(api)
Run Code Online (Sandbox Code Playgroud)

远程仓库:

@ActivityScoped
class RemoteRepositoryImpl @Inject constructor(
    private val api: Api
): RemoteRepository {

    override suspend fun getList(request: ListRequest): PokemonList {
        return api.getPokemonList(request.limit, request.offset)
    }

}
Run Code Online (Sandbox Code Playgroud)

我的问题是: 这怎么行得通?为什么我不必通过 Hilt 提供用例?或者我的设计是错误的,即使这有效,我也应该通过 Hilt 提供用例?

编辑:

如果有帮助的话,链接到 Google I/O域层ui 层。

Pin*_*Pie 5

你的设计很棒!这并没有错,但是,如果您将用例放入单独的模块并根据您的需求确定范围,您可以为用例添加一些额外的上下文。模块的存在主要是为了当您确实有第三方依赖项(最简单的例子是 OkHTTPClient)或当您有接口 -> 接口的实现,或者您想要明显限制/扩展组件的生命周期/可见性时。

目前,您正在告诉 Hilt 如何通过使用 @Inject 注释其构造函数来提供 GetListUseCase 的实例,并且 Hilt 已经知道什么是“CoroutineDispatcher”(因为它是由协程模块中的 @Provides 提供的,对吧?)以及什么是 RemoteRepository(因为您正在注入接口,但在幕后您正在通过 @Provides 在 repo 模块中提供它的真正实现。

所以这就像说 - 给我一个具有两个构造函数依赖项的用例类实例,并且 Hilt 都知道它们,因此不会造成混淆。

如果您想要有一个作用域绑定/组件(如此处所述或将您的用例标记为单例,那么您必须创建一个 UseCaseModule 并在那里定义您的用例组件的范围。