Skip to content

Commit

Permalink
Base repository and viewModel
Browse files Browse the repository at this point in the history
  • Loading branch information
alirezaeiii committed Oct 17, 2023
1 parent ac16a1a commit 2b864e1
Show file tree
Hide file tree
Showing 8 changed files with 121 additions and 96 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -3,21 +3,17 @@ package com.sample.android.tmdb.domain.repository
import android.content.Context
import com.sample.android.tmdb.R
import com.sample.android.tmdb.domain.model.FeedWrapper
import com.sample.android.tmdb.domain.model.TmdbItem
import com.sample.android.tmdb.domain.model.SortType
import com.sample.android.tmdb.util.Resource
import com.sample.android.tmdb.util.isNetworkAvailable
import com.sample.android.tmdb.domain.model.TmdbItem
import kotlinx.coroutines.CoroutineDispatcher
import kotlinx.coroutines.Deferred
import kotlinx.coroutines.async
import kotlinx.coroutines.coroutineScope
import kotlinx.coroutines.flow.flow
import kotlinx.coroutines.flow.flowOn

abstract class BaseFeedRepository<T : TmdbItem>(
private val context: Context,
context: Context,
ioDispatcher: CoroutineDispatcher
) {
) : BaseRepository<List<FeedWrapper<T>>>(context, ioDispatcher) {

protected abstract suspend fun popularItems(): List<T>

Expand All @@ -35,60 +31,52 @@ abstract class BaseFeedRepository<T : TmdbItem>(

protected abstract fun getLatestResId(): Int

val result = flow {
emit(Resource.Loading)
if (context.isNetworkAvailable()) {
try {
coroutineScope {
val trendingDeferred: Deferred<List<T>> = async { trendingItems() }
val popularDeferred: Deferred<List<T>> = async { popularItems() }
val nowPlayingDeferred: Deferred<List<T>> = async { nowPlayingItems() }
val latestDeferred: Deferred<List<T>> = async { latestItems() }
val topRatedDeferred: Deferred<List<T>> = async { topRatedItems() }
val discoverDeferred: Deferred<List<T>> = async { discoverItems() }

emit(
Resource.Success(
listOf(
FeedWrapper(
trendingDeferred.await(),
R.string.text_trending,
SortType.TRENDING
),
FeedWrapper(
popularDeferred.await(),
R.string.text_popular,
SortType.MOST_POPULAR
),
FeedWrapper(
nowPlayingDeferred.await(),
getNowPlayingResId(),
SortType.NOW_PLAYING
),
FeedWrapper(
discoverDeferred.await(),
R.string.text_discover,
SortType.DISCOVER
),
FeedWrapper(
latestDeferred.await(),
getLatestResId(),
SortType.UPCOMING
),
FeedWrapper(
topRatedDeferred.await(),
R.string.text_highest_rate,
SortType.HIGHEST_RATED
)
)
)
)
}
} catch (t: Throwable) {
emit(Resource.Error(context.getString(R.string.failed_loading_msg)))
}
} else {
emit(Resource.Error(context.getString(R.string.failed_network_msg)))
override suspend fun getSuccessResult(): List<FeedWrapper<T>> {
val trendingDeferred: Deferred<List<T>>
val nowPlayingDeferred: Deferred<List<T>>
val popularDeferred: Deferred<List<T>>
val latestDeferred: Deferred<List<T>>
val topRatedDeferred: Deferred<List<T>>
val discoverDeferred: Deferred<List<T>>
coroutineScope {
trendingDeferred = async { trendingItems() }
nowPlayingDeferred = async { nowPlayingItems() }
popularDeferred = async { popularItems() }
latestDeferred = async { latestItems() }
topRatedDeferred = async { topRatedItems() }
discoverDeferred = async { discoverItems() }
}
}.flowOn(ioDispatcher)
return listOf(
FeedWrapper(
trendingDeferred.await(),
R.string.text_trending,
SortType.TRENDING
),
FeedWrapper(
popularDeferred.await(),
R.string.text_popular,
SortType.MOST_POPULAR
),
FeedWrapper(
nowPlayingDeferred.await(),
getNowPlayingResId(),
SortType.NOW_PLAYING
),
FeedWrapper(
discoverDeferred.await(),
R.string.text_discover,
SortType.DISCOVER
),
FeedWrapper(
latestDeferred.await(),
getLatestResId(),
SortType.UPCOMING
),
FeedWrapper(
topRatedDeferred.await(),
R.string.text_highest_rate,
SortType.HIGHEST_RATED
)
)
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
package com.sample.android.tmdb.domain.repository

import android.content.Context
import com.sample.android.tmdb.R
import com.sample.android.tmdb.util.Resource
import com.sample.android.tmdb.util.isNetworkAvailable
import kotlinx.coroutines.CoroutineDispatcher
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.flow
import kotlinx.coroutines.flow.flowOn

abstract class BaseRepository<T>(
private val context: Context,
ioDispatcher: CoroutineDispatcher
) {
protected abstract suspend fun getSuccessResult(): T

val result: Flow<Resource<T>> = flow {
emit(Resource.Loading)
if (context.isNetworkAvailable()) {
try {
emit(Resource.Success(getSuccessResult()))
} catch (t: Throwable) {
emit(Resource.Error(context.getString(R.string.failed_loading_msg)))
}
} else {
emit(Resource.Error(context.getString(R.string.failed_network_msg)))
}
}.flowOn(ioDispatcher)
}
31 changes: 31 additions & 0 deletions app/src/main/java/com/sample/android/tmdb/ui/BaseViewModel.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
package com.sample.android.tmdb.ui

import androidx.lifecycle.ViewModel
import androidx.lifecycle.viewModelScope
import com.sample.android.tmdb.domain.repository.BaseRepository
import com.sample.android.tmdb.util.Resource
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.StateFlow
import kotlinx.coroutines.flow.asStateFlow
import kotlinx.coroutines.launch

open class BaseViewModel<T>(
private val repository: BaseRepository<T>
) : ViewModel() {

private val _stateFlow = MutableStateFlow<Resource<T>>(Resource.Loading)
val stateFlow: StateFlow<Resource<T>>
get() = _stateFlow.asStateFlow()

init {
refresh()
}

fun refresh() {
viewModelScope.launch {
repository.result.collect {
_stateFlow.tryEmit(it)
}
}
}
}
31 changes: 4 additions & 27 deletions app/src/main/java/com/sample/android/tmdb/ui/feed/FeedViewModel.kt
Original file line number Diff line number Diff line change
@@ -1,33 +1,10 @@
package com.sample.android.tmdb.ui.feed

import androidx.lifecycle.ViewModel
import androidx.lifecycle.viewModelScope
import com.sample.android.tmdb.domain.model.FeedWrapper
import com.sample.android.tmdb.domain.model.TmdbItem
import com.sample.android.tmdb.domain.repository.BaseFeedRepository
import com.sample.android.tmdb.domain.model.FeedWrapper
import com.sample.android.tmdb.util.Resource
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.StateFlow
import kotlinx.coroutines.flow.asStateFlow
import kotlinx.coroutines.launch
import com.sample.android.tmdb.ui.BaseViewModel

open class FeedViewModel<T : TmdbItem>(
private val repository: BaseFeedRepository<T>
) : ViewModel() {

private val _stateFlow = MutableStateFlow<Resource<List<FeedWrapper<T>>>>(Resource.Loading)
val stateFlow: StateFlow<Resource<List<FeedWrapper<T>>>>
get() = _stateFlow.asStateFlow()

init {
refresh()
}

fun refresh() {
viewModelScope.launch {
repository.result.collect {
_stateFlow.tryEmit(it)
}
}
}
}
repository: BaseFeedRepository<T>,
) : BaseViewModel<List<FeedWrapper<T>>>(repository)
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ import com.sample.android.tmdb.widget.MarginDecoration

abstract class BaseFragment<T : TmdbItem> : BaseNavTypeFragment() {

protected abstract val viewModel: BaseViewModel<T>
protected abstract val viewModel: BasePagingViewModel<T>

private var _binding: FragmentMainBinding? = null

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,7 @@ import com.sample.android.tmdb.util.DisposableManager
import java.util.concurrent.ExecutorService
import java.util.concurrent.Executors

abstract class BaseViewModel<T : TmdbItem>(app: Application)
: AndroidViewModel(app) {
abstract class BasePagingViewModel<T : TmdbItem>(app: Application) : AndroidViewModel(app) {

// thread pool used for network requests
protected val networkIO: ExecutorService = Executors.newFixedThreadPool(5)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,12 @@ package com.sample.android.tmdb.ui.paging.main
import android.app.Application
import androidx.lifecycle.LiveData
import androidx.lifecycle.liveData
import com.sample.android.tmdb.ui.paging.BaseViewModel
import com.sample.android.tmdb.ui.paging.BasePagingViewModel
import com.sample.android.tmdb.domain.model.TmdbItem
import com.sample.android.tmdb.data.paging.Listing
import com.sample.android.tmdb.data.paging.BasePageKeyRepository

abstract class BaseItemViewModel<T : TmdbItem>(app: Application) : BaseViewModel<T>(app) {
abstract class BaseItemViewModel<T : TmdbItem>(app: Application) : BasePagingViewModel<T>(app) {

protected abstract val mainRepoResult : BasePageKeyRepository<T>

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,9 @@ import androidx.lifecycle.Transformations
import com.sample.android.tmdb.domain.model.TmdbItem
import com.sample.android.tmdb.data.paging.Listing
import com.sample.android.tmdb.data.paging.BasePageKeyRepository
import com.sample.android.tmdb.ui.paging.BaseViewModel
import com.sample.android.tmdb.ui.paging.BasePagingViewModel

abstract class BaseSearchViewModel<T : TmdbItem>(app: Application) : BaseViewModel<T>(app) {
abstract class BaseSearchViewModel<T : TmdbItem>(app: Application) : BasePagingViewModel<T>(app) {

private val query = MutableLiveData<String>()

Expand Down

0 comments on commit 2b864e1

Please sign in to comment.