Skip to content

Instantly share code, notes, and snippets.

@pask23
Last active March 21, 2022 14:24
Show Gist options
  • Select an option

  • Save pask23/4b41c3b3d11c3ab243b87efe5a4d5eb1 to your computer and use it in GitHub Desktop.

Select an option

Save pask23/4b41c3b3d11c3ab243b87efe5a4d5eb1 to your computer and use it in GitHub Desktop.
Example Clean Architecture
//Data Layer
// data/repositories/book
class BooksRemoteDataSourceImpl(
private val service: BooksApi,
private val mapper: BookApiResponseMapper
) : BooksRemoteDataSource {
override suspend fun getBooks(author: String): Result<List<Volume>> =
withContext(Dispatchers.IO) {
try {
val response = service.getBooks(author)
if (response.isSuccessful) {
return@withContext Result.Success(mapper.toVolumeList(response.body()!!))
} else {
return@withContext Result.Error(Exception(response.message()))
}
} catch (e: Exception) {
return@withContext Result.Error(e)
}
}
}
//Data Layers
// data/repositories/book
class BooksRepositoryImpl(
private val localDataSource: BooksLocalDataSource, //nel caso abbiamo anche il local data soruce
private val remoteDataSource: BooksRemoteDataSource
) : BooksRepository {
override suspend fun getRemoteBooks(author: String): Result<List<Volume>> {
return remoteDataSource.getBooks(author)
}
}
//Presentation Layer
class BooksViewModel(
private val getBooksUseCase: GetBooksUseCase,
private val mapper: BookWithStatusMapper
) : ViewModel() {
private val _dataLoading = MutableLiveData(true)
val dataLoading: LiveData<Boolean> = _dataLoading
private val _books = MutableLiveData<List<BookWithStatus>>()
val books = _books
private val _error = MutableLiveData<String>()
val error: LiveData<String> = _error
private val _remoteBooks = arrayListOf<Volume>()
// Getting books with uncle bob as default author :)
fun getBooks(author: String) {
viewModelScope.launch {
_dataLoading.postValue(true)
when (val booksResult = getBooksUseCase.invoke(author)) {
is Result.Success -> {
_remoteBooks.clear()
_remoteBooks.addAll(booksResult.data)
books.value = mapper.fromVolumeToBookWithStatus(_remoteBooks)
_dataLoading.postValue(false)
}
is Result.Error -> {
_dataLoading.postValue(false)
books.value = emptyList()
_error.postValue(booksResult.exception.message)
}
}
}
}
class BooksViewModelFactory(
private val getBooksUseCase: GetBooksUseCase,
private val mapper: BookWithStatusMapper
) :
ViewModelProvider.NewInstanceFactory() {
@Suppress("UNCHECKED_CAST")
override fun <T : ViewModel?> create(modelClass: Class<T>): T {
return BooksViewModel(
getBooksUseCase
mapper
) as T
}
}
}
//Domain Layer
// domain/usecases
class GetBooksUseCase(private val booksRepository: BooksRepository) {
suspend operator fun invoke(author: String) = booksRepository.getRemoteBooks(author)
}
//Data Layer: retrofit api
// data/api
interface IBooksApi {
@GET("books/v1/volumes")
suspend fun getBooks(@Query("q") author: String): Response<BooksApiResponse>
}
//Data Layers
// data/repositories/book
interface IBooksRemoteDataSource {
suspend fun getBooks(author: String): Result<List<Volume>>
}
//Domain Layer, package repositories
// domain/repositories
interface IBooksRepository {
suspend fun getRemoteBooks(author: String): Result<List<Volume>>
}
//Domain Layer
// domain/common
sealed class Result<out R> {
data class Success<out T>(val data: T) : Result<T>()
data class Error(val exception: Exception) : Result<Nothing>()
override fun toString(): String {
return when (this) {
is Success<*> -> "Success[data=$data]"
is Error -> "Error[exception=$exception]"
}
}
}
@pask23

pask23 commented Mar 17, 2022

Copy link
Copy Markdown
Author

Api in Data Layer
DataSource in Data Layer
interface Repository in Domain Layer
implementazione Repository in Data Layer
UseCase in Domain Layer
ViewModel in Presentation Layer

viewModel ---[richiama]---> useCase ---[richiama]---> repository ---[richiama]---> dataSource ---[richiama]---> Api

se si vuole evitare di usare lo useCase (io sono per farlo e lo rivediamo in un prossimo ticket dato che si andrà ad integrare la parte di DH comandi) allora è il viewModel a richiamare il repository

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment