Create an account

Very important

  • To access the important data of the forums, you must be active in each forum and especially in the leaks and database leaks section, send data and after sending the data and activity, data and important content will be opened and visible for you.
  • You will only see chat messages from people who are at or below your level.
  • More than 500,000 database leaks and millions of account leaks are waiting for you, so access and view with more activity.
  • Many important data are inactive and inaccessible for you, so open them with activity. (This will be done automatically)


Thread Rating:
  • 454 Vote(s) - 3.58 Average
  • 1
  • 2
  • 3
  • 4
  • 5
Which is better to put the Coroutine call in the Repository or the ViewModel?

#1
Just wondering others opinion I have 2 ways I can go about doing something and was curious which is better (and hopefully why you think so)

I have 2 files WordRepository and WordViewModel. I can either do the coroutines in the Repo or in the ViewModel both ways work, but hoping someone can give me a clue as to why I would do the coroutines in one or the other and vice versa.

Version A.(Where the coroutine is in the Repo)

WordRepo:

class WordRepository(private val wordDao: WordDao): WordRepo {

@WorkerThread
override suspend fun deleteAllLogsOlderThan(XDays: Int): Int = withContext(IO) {
return@withContext wordDao.deleteAll()
}

}

WordViewModel:

class WordViewModel(private val wordRepository: WordRepo) : ViewModel() {

fun deleteAllLogsOlderThanA(XDays:Int): Int = runBlocking {
wordRepository.deleteAllLogsOlderThan(XDays)
}

}

Version B.(Where the coroutine is in the ViewModel)

Word Repo:
class WordRepository(private val wordDao: WordDao): WordRepo {

@WorkerThread
override suspend fun deleteAllLogsOlderThan(XDays: Int): Int = wordDao.deleteAll()

}

WordViewModel:
class WordViewModel(private val wordRepository: WordRepo) : ViewModel() {

fun deleteAllLogsOlderThanA(XDays:Int): Int = runBlocking {
withContext(IO) {
wordRepository.deleteAllLogsOlderThan(XDays)
}
}

}
Reply

#2
I think either way is fine honestly but if I have to choose I prefer keeping thread related code in the repository layer. (*Version A* in the example)

My justification:

(A) View Models should not assume how Repositories internally work. *Version B* implies that the View Model assumes that the Repository will run on the calling thread.

(B) Also, the repository should not depend on other components to use a specific thread to call its method. The repository should be complete by itself.

© To avoid code duplication. Having multiple View models calling one repository method is a very common situation. *Version A* wins in this case because you only need `Corountine` in one place, the repository.

<br>

I suggest looking at some of the Google Samples to see where they like to handle `Coroutine` and data access threading codes.

1. [Sunflower][1] uses `Coroutine` code in their repository. This is probably particularly useful for you because it includes examples of fire-and-forget type of requests.

2. [GitHubBrowserRepo][2] does not use `Coroutine` but the repository keeps reference to the `Executor` instances that are used when accessing the data.


[1]:

[To see links please register here]

[2]:

[To see links please register here]

Reply

#3
The question is where to specify that repository jobs should run on IO threads pools:

- A) In Repository
- B) In ViewModel

Frankly I am not sure which way is better.

B) Having it in ViewModel means more transparency of what runs on which thread. This is also the way I mostly worked with RxJava. As a negative your ViewModel will be cluttered with thread switching (withContext()), while it's actually obvious that all repository job should run on the background thread. So is this extra information any useful?

A) Having it in Repository means more flexibility regarding thread switching in repository and cleaner code in ViewModel. Code will be less explicit from ViewModel point of view about threads. As a negative all repository methods will need to be suspended, so thus usable only from coroutines.
Reply

#4
Android best practice suggest generally co-routines should be used inside view model but in some cases it should be good to use inside repository as well.

**The ViewModel should create coroutines**

ViewModel classes should prefer creating coroutines instead of exposing suspend functions to perform business logic. Suspend functions in the ViewModel can be useful if instead of exposing state using a stream of data, only a single value needs to be emitted.

The data and business layer should expose suspend functions and Flows
Classes in the data and business layers generally expose functions to perform one-shot calls or to be notified of data changes over time. Classes in those layers should expose suspend functions for one-shot calls and Flow to notify about data changes.


// Classes in the data and business layer expose
// either suspend functions or Flows

class ExampleRepository {
suspend fun makeNetworkRequest() { /* ... */ }

fun getExamples(): Flow<Example> { /* ... */ }
}


Creating coroutines in the business and data layer
For classes in the data or business layer that need to create coroutines for different reasons, there are different options.

If the work to be done in those coroutines is relevant only when the user is present on the current screen, it should follow the caller's lifecycle. In most cases, the caller will be the ViewModel, and the call will be cancelled when the user navigates away from the screen and the ViewModel is cleared. In this case, coroutineScope or supervisorScope should be used.

class GetAllBooksAndAuthorsUseCase(
private val booksRepository: BooksRepository,
private val authorsRepository: AuthorsRepository,
) {
suspend fun getBookAndAuthors(): BookAndAuthors {
// In parallel, fetch books and authors and return when both requests
// complete and the data is ready
return coroutineScope {
val books = async { booksRepository.getAllBooks() }
val authors = async { authorsRepository.getAllAuthors() }
BookAndAuthors(books.await(), authors.await())
}
}
}

source

[To see links please register here]

Reply



Forum Jump:


Users browsing this thread:
1 Guest(s)

©0Day  2016 - 2023 | All Rights Reserved.  Made with    for the community. Connected through