Update App Architecture

This commit is contained in:
2021-09-07 05:36:04 +02:00
parent 1367955396
commit abb21c994f
53 changed files with 867 additions and 245 deletions
@@ -17,8 +17,11 @@ class RemoteAnimatorDataSource @Inject constructor(
override fun findAll(): Flow<Result<List<Animator>>> {
return flow {
try {
val data = httpClient.get<AnimatorApiResponse>(ApiUrl.Animator.featured)
emit(Result.Success(data.animatorAnimatorData.featuredAnimators.results))
val result = httpClient.get<AnimatorApiResponse>(ApiUrl.Animator.featured)
val identifiableData = result.data.animators.results.mapIndexed { index, animator ->
animator.copy(id = index.toLong())
}
emit(Result.Success(identifiableData))
} catch (e: Exception) {
emit(Result.Error(e))
}
@@ -17,12 +17,14 @@ class RemoteBlogDataSource @Inject constructor(
return flow {
try {
val data = httpClient.get<BlogApiResponse>(ApiUrl.Blog.latest)
emit(Result.Success(data.blogBlogData.blogPage.blogs))
val identifiableData = data.data.blogs.results.mapIndexed { index, blog ->
blog.copy(id = index.toLong())
}
emit(Result.Success(identifiableData))
} catch (e: Exception) {
emit(Result.Error(e))
}
}
}
override suspend fun save(blog: Blog) {
@@ -11,19 +11,19 @@ class LocalLottieFileDataSource @Inject constructor(
private val lottieFileDao: LottieFilesDao
) : LottieFileDataSource {
override fun findRecent(): Flow<Result<List<Lottiefile>>> {
return lottieFileDao.findRecent().map {
return lottieFileDao.findByType("recent").map {
Result.Success(it)
}
}
override fun findPopular(): Flow<Result<List<Lottiefile>>> {
return lottieFileDao.findPopular().map {
return lottieFileDao.findByType("popular").map {
Result.Success(it)
}
}
override fun findFeatured(): Flow<Result<List<Lottiefile>>> {
return lottieFileDao.findFeatured().map {
return lottieFileDao.findByType("featured").map {
Result.Success(it)
}
}
@@ -7,6 +7,7 @@ import com.ericampire.android.androidstudycase.util.Result
import io.ktor.client.*
import io.ktor.client.request.*
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.FlowCollector
import kotlinx.coroutines.flow.flow
import javax.inject.Inject
@@ -14,11 +15,14 @@ class RemoteLottieFileDataSource @Inject constructor(
private val httpClient: HttpClient
) : LottieFileDataSource {
private fun find(url: String): Flow<Result<List<Lottiefile>>> {
private fun find(
url: String,
action: suspend FlowCollector<Result<List<Lottiefile>>>.(LottieFilesApiResponse) -> Unit
): Flow<Result<List<Lottiefile>>> {
return flow {
try {
val data = httpClient.get<LottieFilesApiResponse>(url)
emit(Result.Success(data.lottieFilesLottieFilesData.page.results))
action(data)
} catch (e: Exception) {
emit(Result.Error(e))
}
@@ -26,15 +30,24 @@ class RemoteLottieFileDataSource @Inject constructor(
}
override fun findRecent(): Flow<Result<List<Lottiefile>>> {
return find(ApiUrl.LottieFile.recent)
return find(ApiUrl.LottieFile.recent) { response ->
val animations = response.lottieFilesLottieFilesData.recent?.results ?: emptyList()
emit(Result.Success(animations))
}
}
override fun findPopular(): Flow<Result<List<Lottiefile>>> {
return find(ApiUrl.LottieFile.popular)
return find(ApiUrl.LottieFile.popular) { response ->
val animations = response.lottieFilesLottieFilesData.popular?.results ?: emptyList()
emit(Result.Success(animations))
}
}
override fun findFeatured(): Flow<Result<List<Lottiefile>>> {
return find(ApiUrl.LottieFile.featured)
return find(ApiUrl.LottieFile.featured) { response ->
val animations = response.lottieFilesLottieFilesData.featured?.results ?: emptyList()
emit(Result.Success(animations))
}
}
override suspend fun save(lottiefile: Lottiefile) {
@@ -15,10 +15,13 @@ import com.ericampire.android.androidstudycase.domain.repository.AnimatorReposit
import com.ericampire.android.androidstudycase.domain.repository.BlogRepository
import com.ericampire.android.androidstudycase.domain.repository.LottieFileRepository
import com.ericampire.android.androidstudycase.domain.repository.UserRepository
import com.ericampire.android.androidstudycase.util.IoDispatcher
import dagger.Module
import dagger.Provides
import dagger.hilt.InstallIn
import dagger.hilt.components.SingletonComponent
import kotlinx.coroutines.CoroutineDispatcher
import kotlinx.coroutines.CoroutineScope
@Module
@@ -29,10 +32,14 @@ object RepositoryModule {
fun provideAnimatorRepository(
localDataSource: LocalAnimatorDataSource,
remoteDataSource: RemoteAnimatorDataSource,
@IoDispatcher coroutineDispatcher: CoroutineDispatcher,
coroutineScope: CoroutineScope
): AnimatorRepository {
return AnimatorRepositoryImpl(
localDataSource = localDataSource,
remoteDataSource = remoteDataSource
remoteDataSource = remoteDataSource,
coroutineDispatcher = coroutineDispatcher,
coroutineScope = coroutineScope
)
}
@@ -49,10 +56,14 @@ object RepositoryModule {
fun provideLottieFileRepository(
localDataSource: LocalLottieFileDataSource,
remoteDataSource: RemoteLottieFileDataSource,
@IoDispatcher coroutineDispatcher: CoroutineDispatcher,
coroutineScope: CoroutineScope
): LottieFileRepository {
return LottieFileRepositoryImpl(
localDataSource = localDataSource,
remoteDataSource = remoteDataSource
remoteDataSource = remoteDataSource,
coroutineDispatcher = coroutineDispatcher,
coroutineScope = coroutineScope
)
}
@@ -60,10 +71,14 @@ object RepositoryModule {
fun provideBlogRepository(
localDataSource: LocalBlogDataSource,
remoteDataSource: RemoteBlogDataSource,
@IoDispatcher coroutineDispatcher: CoroutineDispatcher,
coroutineScope: CoroutineScope
) : BlogRepository {
return BlogRepositoryImpl(
localDataSource = localDataSource,
remoteDataSource = remoteDataSource
remoteDataSource = remoteDataSource,
coroutineDispatcher = coroutineDispatcher,
coroutineScope = coroutineScope
)
}
}
@@ -3,15 +3,21 @@ package com.ericampire.android.androidstudycase.data.repository
import com.ericampire.android.androidstudycase.data.datasource.animator.AnimatorDataSource
import com.ericampire.android.androidstudycase.domain.entity.Animator
import com.ericampire.android.androidstudycase.domain.repository.AnimatorRepository
import com.ericampire.android.androidstudycase.util.IoDispatcher
import com.ericampire.android.androidstudycase.util.Result
import kotlinx.coroutines.CoroutineDispatcher
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.collect
import kotlinx.coroutines.launch
import javax.inject.Inject
class AnimatorRepositoryImpl @Inject constructor(
private val remoteDataSource: AnimatorDataSource,
private val localDataSource: AnimatorDataSource,
private val coroutineScope: CoroutineScope,
@IoDispatcher private val coroutineDispatcher: CoroutineDispatcher
) : AnimatorRepository {
override fun findAll(): Flow<Result<List<Animator>>> {
refreshData()
@@ -19,7 +25,7 @@ class AnimatorRepositoryImpl @Inject constructor(
}
private fun refreshData() {
suspend {
coroutineScope.launch(coroutineDispatcher) {
remoteDataSource.findAll().collect {
if (it is Result.Success) {
it.data.forEach { animator ->
@@ -3,14 +3,20 @@ package com.ericampire.android.androidstudycase.data.repository
import com.ericampire.android.androidstudycase.data.datasource.blog.BlogDataSource
import com.ericampire.android.androidstudycase.domain.entity.Blog
import com.ericampire.android.androidstudycase.domain.repository.BlogRepository
import com.ericampire.android.androidstudycase.util.IoDispatcher
import com.ericampire.android.androidstudycase.util.Result
import kotlinx.coroutines.CoroutineDispatcher
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.collect
import kotlinx.coroutines.launch
import javax.inject.Inject
class BlogRepositoryImpl @Inject constructor(
private val remoteDataSource: BlogDataSource,
private val localDataSource: BlogDataSource,
private val coroutineScope: CoroutineScope,
@IoDispatcher private val coroutineDispatcher: CoroutineDispatcher
) : BlogRepository {
override fun findAll(): Flow<Result<List<Blog>>> {
refreshData()
@@ -18,7 +24,7 @@ class BlogRepositoryImpl @Inject constructor(
}
private fun refreshData() {
suspend {
coroutineScope.launch(coroutineDispatcher) {
remoteDataSource.findAll().collect {
if (it is Result.Success) {
it.data.forEach { blog ->
@@ -3,41 +3,44 @@ package com.ericampire.android.androidstudycase.data.repository
import com.ericampire.android.androidstudycase.data.datasource.lottiefiles.LottieFileDataSource
import com.ericampire.android.androidstudycase.domain.entity.Lottiefile
import com.ericampire.android.androidstudycase.domain.repository.LottieFileRepository
import com.ericampire.android.androidstudycase.util.IoDispatcher
import com.ericampire.android.androidstudycase.util.Result
import kotlinx.coroutines.CoroutineDispatcher
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.collect
import kotlinx.coroutines.launch
import javax.inject.Inject
class LottieFileRepositoryImpl @Inject constructor(
private val localDataSource: LottieFileDataSource,
private val remoteDataSource: LottieFileDataSource,
private val coroutineScope: CoroutineScope,
@IoDispatcher private val coroutineDispatcher: CoroutineDispatcher
) : LottieFileRepository {
override fun findRecent(): Flow<Result<List<Lottiefile>>> {
val recentFiles = remoteDataSource.findRecent()
refreshData(recentFiles)
return recentFiles
refreshData(remoteDataSource.findRecent(), "recent")
return localDataSource.findRecent()
}
private fun refreshData(data: Flow<Result<List<Lottiefile>>>) {
suspend {
private fun refreshData(data: Flow<Result<List<Lottiefile>>>, type: String) {
coroutineScope.launch(coroutineDispatcher) {
data.collect {
if (it is Result.Success) {
it.data.forEach { file -> localDataSource.save(file) }
it.data.forEach { file -> localDataSource.save(file.copy(type = type)) }
}
}
}
}
override fun findPopular(): Flow<Result<List<Lottiefile>>> {
val files = remoteDataSource.findPopular()
refreshData(files)
return files
refreshData(remoteDataSource.findPopular(), "popular")
return localDataSource.findPopular()
}
override fun findFeatured(): Flow<Result<List<Lottiefile>>> {
val files = remoteDataSource.findFeatured()
refreshData(files)
return files
refreshData(remoteDataSource.findFeatured(), "featured")
return localDataSource.findFeatured()
}
}
@@ -12,12 +12,6 @@ interface LottieFilesDao {
@Insert(onConflict = OnConflictStrategy.REPLACE)
suspend fun save(lottiefile: Lottiefile)
@Query("SELECT * FROM Lottiefile")
fun findPopular(): Flow<List<Lottiefile>>
@Query("SELECT * FROM Lottiefile")
fun findFeatured(): Flow<List<Lottiefile>>
@Query("SELECT * FROM Lottiefile")
fun findRecent(): Flow<List<Lottiefile>>
@Query("SELECT * FROM Lottiefile WHERE type = :type")
fun findByType(type: String): Flow<List<Lottiefile>>
}