Update App Architecture
This commit is contained in:
+5
-2
@@ -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))
|
||||
}
|
||||
|
||||
+4
-2
@@ -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) {
|
||||
|
||||
+3
-3
@@ -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)
|
||||
}
|
||||
}
|
||||
|
||||
+18
-5
@@ -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) {
|
||||
|
||||
+18
-3
@@ -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
|
||||
)
|
||||
}
|
||||
}
|
||||
+7
-1
@@ -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 ->
|
||||
|
||||
+7
-1
@@ -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 ->
|
||||
|
||||
+15
-12
@@ -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()
|
||||
}
|
||||
}
|
||||
+2
-8
@@ -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>>
|
||||
}
|
||||
Reference in New Issue
Block a user