2
\$\begingroup\$

I am implementing some of the architectural designs from Google I/O's app to my own app, but I have come across something in their app that has created some confusion for me.

They have a domain layer with repository usecases, which I use myself in my apps usually. However, I do have to provide these usecases with dagger in my app. But on Google's I/O app, I cannot find any module that provides these usecases. And when used with viewmodels annotated @HiltViewModel (In my own app), it seems like it works? Somehow these get injected into my viewmodels. I do have to provide all the usecase's dependencies(repositories etc) with Hilt, but I don't have to provide any usecase via Hilt.

Here is how my app architecture looks like:

enter image description here

Here is example how it looks in my code.

Usecase:

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
}

Concrete implementation of 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)
 }
}

Viewmodel:

@HiltViewModel
class DetailViewModel @Inject constructor(
 private val GetListUseCase: getListUseCase
): ViewModel() {
 suspend fun getList(): Resource<ItemsList> {
 getPokemonListUseCase.invoke(ListRequest(3))
 }
}

Example of provided repo:

@Singleton
@Provides
fun provideRemoteRepository(
 api: Api
): RemoteRepository = RemoteRepositoryImpl(api)

Remote repo:

@ActivityScoped
class RemoteRepositoryImpl @Inject constructor(
 private val api: Api
): RemoteRepository {
 override suspend fun getList(request: ListRequest): PokemonList {
 return api.getPokemonList(request.limit, request.offset)
 }
}

My Question is: Is this correct way of using Usecases? Should I also provide these with DI from a module as I do with all other dependencies in my project ? And why does this even work from the first place? How come I don't need to provide usecases with DI?

And should I have a single Repository class, which has remote datasource and local datasource as dependencies, or should I have a Repository class for each one? It is the same type of data that gets fetches from a remote source and then cached locally.

I can't find anything on the Google I/O app github repo where they have any kind of dependency injections where they provide usecases. I see that they are using delegates and delegatemodules to provide some of the dependencies to the viewmode, but nothing to provide usecases.

asked Jul 15, 2022 at 18:09
\$\endgroup\$

0

Know someone who can answer? Share a link to this question via email, Twitter, or Facebook.

Your Answer

Draft saved
Draft discarded

Sign up or log in

Sign up using Google
Sign up using Email and Password

Post as a guest

Required, but never shown

Post as a guest

Required, but never shown

By clicking "Post Your Answer", you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.