Last active
March 21, 2022 14:24
-
-
Save pask23/4b41c3b3d11c3ab243b87efe5a4d5eb1 to your computer and use it in GitHub Desktop.
Example Clean Architecture
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| //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) | |
| } | |
| } | |
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| //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) | |
| } | |
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| //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 | |
| } | |
| } | |
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| //Domain Layer | |
| // domain/usecases | |
| class GetBooksUseCase(private val booksRepository: BooksRepository) { | |
| suspend operator fun invoke(author: String) = booksRepository.getRemoteBooks(author) | |
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| //Data Layer: retrofit api | |
| // data/api | |
| interface IBooksApi { | |
| @GET("books/v1/volumes") | |
| suspend fun getBooks(@Query("q") author: String): Response<BooksApiResponse> | |
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| //Data Layers | |
| // data/repositories/book | |
| interface IBooksRemoteDataSource { | |
| suspend fun getBooks(author: String): Result<List<Volume>> | |
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| //Domain Layer, package repositories | |
| // domain/repositories | |
| interface IBooksRepository { | |
| suspend fun getRemoteBooks(author: String): Result<List<Volume>> | |
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| //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]" | |
| } | |
| } | |
| } |
Author
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
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