Skip to content

Commit

Permalink
[refactor] : #83 Ui State Pattern, Home WeekFood StateFlow Migration
Browse files Browse the repository at this point in the history
  • Loading branch information
SsongSik committed Jun 18, 2023
1 parent d90e6b0 commit 85d43ee
Show file tree
Hide file tree
Showing 11 changed files with 90 additions and 58 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -7,12 +7,14 @@ import retrofit2.HttpException
import retrofit2.Response
import java.net.SocketException

fun <T> safeApiCall(call: suspend () -> Response<T>): Flow<BaseResult<T>> = flow {
fun <T, R> autoHandleApiResponse(transform: ((T) -> R)? = null, block: suspend () -> Response<T>): Flow<BaseResult<R>> = flow {
try {
val response = call()
val response = block()
val body = response.body()
if (response.isSuccessful && body != null) {
emit(BaseResult.Success(body))
transform?.invoke(body)?.let {
emit(BaseResult.Success(it))
} ?: emit(BaseResult.Error(response.code()))
} else {
emit(BaseResult.Error(response.code()))
}
Expand All @@ -23,4 +25,4 @@ fun <T> safeApiCall(call: suspend () -> Response<T>): Flow<BaseResult<T>> = flow
else -> emit(BaseResult.Error(ErrorConstant.EVENT_UNKNOWN_HOST_EXCEPTION))
}
}
}
}
Original file line number Diff line number Diff line change
@@ -1,12 +1,14 @@
package com.myongsik.myongsikandroid.data.datasource.food

import com.myongsik.myongsikandroid.base.BaseResult
import com.myongsik.myongsikandroid.domain.model.food.RequestReviewDataEntity
import com.myongsik.myongsikandroid.domain.model.food.ResponseReviewDataEntity
import com.myongsik.myongsikandroid.domain.model.food.ResponseWeekFoodEntity
import kotlinx.coroutines.flow.Flow

interface FoodDataSource {

suspend fun weekGetFoodArea(s: String): ResponseWeekFoodEntity?
suspend fun weekGetFoodArea(s: String): Flow<BaseResult<ResponseWeekFoodEntity>>

suspend fun postReview(requestReviewDataEntity: RequestReviewDataEntity): ResponseReviewDataEntity?

Expand Down
Original file line number Diff line number Diff line change
@@ -1,26 +1,22 @@
package com.myongsik.myongsikandroid.data.datasource.food

import android.util.Log
import com.myongsik.myongsikandroid.base.autoHandleApiResponse
import com.myongsik.myongsikandroid.data.api.HomeFoodApi
import com.myongsik.myongsikandroid.data.model.food.toWeekFoodEntity
import com.myongsik.myongsikandroid.data.model.review.toRequestReviewData
import com.myongsik.myongsikandroid.data.model.review.toResponseReviewEntity
import com.myongsik.myongsikandroid.domain.model.food.RequestReviewDataEntity
import com.myongsik.myongsikandroid.domain.model.food.ResponseReviewDataEntity
import com.myongsik.myongsikandroid.domain.model.food.ResponseWeekFoodEntity
import kotlinx.coroutines.flow.map
import javax.inject.Inject

class FoodDataSourceImpl @Inject constructor(
private val homeFoodApi : HomeFoodApi
) : FoodDataSource {

override suspend fun weekGetFoodArea(s: String): ResponseWeekFoodEntity? {
val response = homeFoodApi.weekGetFoodArea(s)
return if(response.isSuccessful) {
response.body()?.toWeekFoodEntity()
} else {
null
}
override suspend fun weekGetFoodArea(s: String) = autoHandleApiResponse({ it.toWeekFoodEntity() }) {
homeFoodApi.weekGetFoodArea(s)
}

override suspend fun postReview(requestReviewDataEntity: RequestReviewDataEntity): ResponseReviewDataEntity? {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,13 +1,9 @@
package com.myongsik.myongsikandroid.data.repository.food

import androidx.datastore.preferences.core.Preferences
import com.myongsik.myongsikandroid.base.ApiResponse
import com.myongsik.myongsikandroid.data.model.food.DayFoodResponse
import com.myongsik.myongsikandroid.data.model.food.RankRestaurantResponse
import com.myongsik.myongsikandroid.data.model.food.ResponseOneRestaurant
import com.myongsik.myongsikandroid.data.model.food.WeekFoodResponse
import com.myongsik.myongsikandroid.data.model.review.RequestReviewData
import com.myongsik.myongsikandroid.data.model.review.ResponseReviewData
import kotlinx.coroutines.flow.Flow
import retrofit2.Response

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,15 +5,10 @@ import androidx.datastore.core.DataStore
import androidx.datastore.preferences.core.Preferences
import androidx.datastore.preferences.core.edit
import androidx.datastore.preferences.core.emptyPreferences
import com.myongsik.myongsikandroid.base.ApiResponse
import com.myongsik.myongsikandroid.base.safeApiCall
import com.myongsik.myongsikandroid.data.api.HomeFoodApi
import com.myongsik.myongsikandroid.data.model.food.DayFoodResponse
import com.myongsik.myongsikandroid.data.model.food.RankRestaurantResponse
import com.myongsik.myongsikandroid.data.model.food.ResponseOneRestaurant
import com.myongsik.myongsikandroid.data.model.food.WeekFoodResponse
import com.myongsik.myongsikandroid.data.model.review.RequestReviewData
import com.myongsik.myongsikandroid.data.model.review.ResponseReviewData
import com.myongsik.myongsikandroid.util.DataStoreKey
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.catch
Expand Down
Original file line number Diff line number Diff line change
@@ -1,18 +1,20 @@
package com.myongsik.myongsikandroid.data.repository.food

import android.util.Log
import com.myongsik.myongsikandroid.base.BaseResult
import com.myongsik.myongsikandroid.data.datasource.food.FoodDataSource
import com.myongsik.myongsikandroid.domain.model.food.RequestReviewDataEntity
import com.myongsik.myongsikandroid.domain.model.food.ResponseReviewDataEntity
import com.myongsik.myongsikandroid.domain.model.food.ResponseWeekFoodEntity
import com.myongsik.myongsikandroid.domain.repository.food.FoodV2Repository
import kotlinx.coroutines.flow.Flow
import javax.inject.Inject

class FoodV2RepositoryImpl @Inject constructor(
private val foodDataSource: FoodDataSource
) : FoodV2Repository {

override suspend fun weekGetFoodArea(s: String): ResponseWeekFoodEntity? {
override suspend fun weekGetFoodArea(s: String): Flow<BaseResult<ResponseWeekFoodEntity>> {
return foodDataSource.weekGetFoodArea(s)
}

Expand Down
Original file line number Diff line number Diff line change
@@ -1,12 +1,14 @@
package com.myongsik.myongsikandroid.domain.repository.food

import com.myongsik.myongsikandroid.base.BaseResult
import com.myongsik.myongsikandroid.domain.model.food.RequestReviewDataEntity
import com.myongsik.myongsikandroid.domain.model.food.ResponseReviewDataEntity
import com.myongsik.myongsikandroid.domain.model.food.ResponseWeekFoodEntity
import kotlinx.coroutines.flow.Flow

interface FoodV2Repository {

suspend fun weekGetFoodArea(s: String): ResponseWeekFoodEntity?
suspend fun weekGetFoodArea(s: String): Flow<BaseResult<ResponseWeekFoodEntity>>

suspend fun postReview(requestReviewDataEntity: RequestReviewDataEntity): ResponseReviewDataEntity?
}
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,5 @@ import javax.inject.Inject
class GetWeekFoodDataUseCase @Inject constructor(
private val foodV2Repository: FoodV2Repository
){

suspend operator fun invoke(s : String) = foodV2Repository.weekGetFoodArea(s)
}
Original file line number Diff line number Diff line change
Expand Up @@ -27,15 +27,15 @@ import com.google.android.gms.ads.interstitial.InterstitialAd
import com.google.android.gms.ads.interstitial.InterstitialAdLoadCallback
import com.google.android.material.bottomsheet.BottomSheetBehavior
import com.google.android.material.bottomsheet.BottomSheetDialog
import com.myongsik.myongsikandroid.base.BaseFragment
import com.myongsik.myongsikandroid.BuildConfig
import com.myongsik.myongsikandroid.R
import com.myongsik.myongsikandroid.base.ApiResponse
import com.myongsik.myongsikandroid.base.BaseFragment
import com.myongsik.myongsikandroid.data.model.review.RequestReviewData
import com.myongsik.myongsikandroid.databinding.DialogBottomUpdateSheetBinding
import com.myongsik.myongsikandroid.databinding.FragmentHomeBinding
import com.myongsik.myongsikandroid.presentation.adapter.food.MyPagerAdapter
import com.myongsik.myongsikandroid.presentation.viewmodel.food.HomeViewModel
import com.myongsik.myongsikandroid.presentation.viewmodel.food.WeekFoodState
import com.myongsik.myongsikandroid.util.*
import dagger.hilt.android.AndroidEntryPoint
import kotlinx.coroutines.delay
Expand Down Expand Up @@ -76,12 +76,6 @@ class HomeFragment : BaseFragment<FragmentHomeBinding>() {
initInterstitialAd()
setInterstitialAd()
}

initData()
initViewPager()
initViews()
chekNetwork()
checkWeekend()
}

override fun initListener() {
Expand Down Expand Up @@ -113,27 +107,47 @@ class HomeFragment : BaseFragment<FragmentHomeBinding>() {
private fun initObserve() {
viewLifecycleOwner.lifecycleScope.launch{
viewLifecycleOwner.repeatOnLifecycle(Lifecycle.State.STARTED) {
homeViewModel.weekGetFoodArea.collectLatest {
val list = mutableListOf<List<String>>()
homeViewModel.weekGetFoodArea.collect {
when(it) {
is WeekFoodState.UnInitialized -> {
initData()
initViewPager()
initViews()
chekNetwork()
checkWeekend()
}

it?.let{
settingDate(LocalDate.parse(it.localDateTime.substring(0, 10)))
is WeekFoodState.Loading -> {

it.data.forEach { foodResult ->
list.add(foodResult.meals)
}

val chunkedList = if (list.size == 15) {
list.chunked(3).chunked(5).first()
} else {
list.chunked(2).chunked(5).first()
is WeekFoodState.SuccessWeekFoodGetData -> {
val list = mutableListOf<List<String>>()

it.let{
settingDate(LocalDate.parse(it.getWeekFoodData.localDateTime.substring(0, 10)))

it.getWeekFoodData.data.forEach { foodResult ->
list.add(foodResult.meals)
}

val chunkedList = if (list.size == 15) {
list.chunked(3).chunked(5).first()
} else {
list.chunked(2).chunked(5).first()
}

with(binding) {
viewPager2.adapter = MyPagerAdapter(chunkedList)
viewPager2.orientation = ViewPager2.ORIENTATION_HORIZONTAL
setCurrentPage(initDate)
indicator.setViewPager(viewPager2)
}
}
}

with(binding) {
viewPager2.adapter = MyPagerAdapter(chunkedList)
viewPager2.orientation = ViewPager2.ORIENTATION_HORIZONTAL
setCurrentPage(initDate)
indicator.setViewPager(viewPager2)
is WeekFoodState.Error -> {

}
}
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,12 +1,13 @@
package com.myongsik.myongsikandroid.presentation.viewmodel.food

import android.util.Log
import androidx.datastore.preferences.core.Preferences
import androidx.lifecycle.LiveData
import androidx.lifecycle.MutableLiveData
import com.myongsik.myongsikandroid.base.ApiResponse
import com.myongsik.myongsikandroid.base.BaseResult
import com.myongsik.myongsikandroid.base.BaseViewModel
import com.myongsik.myongsikandroid.data.model.food.*
import com.myongsik.myongsikandroid.data.model.food.RankRestaurantResponse
import com.myongsik.myongsikandroid.data.model.food.ResponseMealData
import com.myongsik.myongsikandroid.data.model.food.ResponseOneRestaurant
import com.myongsik.myongsikandroid.data.model.review.RequestReviewData
import com.myongsik.myongsikandroid.data.model.review.ResponseReviewData
import com.myongsik.myongsikandroid.data.model.review.toRequestReviewEntity
Expand All @@ -18,7 +19,10 @@ import com.myongsik.myongsikandroid.util.Constant
import com.myongsik.myongsikandroid.util.MyongsikApplication
import dagger.hilt.android.lifecycle.HiltViewModel
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.flow.*
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.StateFlow
import kotlinx.coroutines.flow.asStateFlow
import kotlinx.coroutines.flow.first
import kotlinx.coroutines.withContext
import javax.inject.Inject

Expand All @@ -29,8 +33,8 @@ class HomeViewModel @Inject constructor(
private val postReviewDataUseCase: PostReviewDataUseCase
) : BaseViewModel() {

private val _weekGetFoodArea = MutableStateFlow<WeekFoodResponse?>(null)
val weekGetFoodArea: StateFlow<WeekFoodResponse?> = _weekGetFoodArea.asStateFlow()
private val _weekGetFoodArea = MutableStateFlow<WeekFoodState>(WeekFoodState.UnInitialized)
val weekGetFoodArea: StateFlow<WeekFoodState> = _weekGetFoodArea.asStateFlow()

private val _postReviewData = MutableStateFlow<ResponseReviewData?>(null)
val postReviewData: StateFlow<ResponseReviewData?> = _postReviewData.asStateFlow()
Expand All @@ -40,16 +44,22 @@ class HomeViewModel @Inject constructor(
get() = _postMealData

fun weekGetFoodAreaFun(s: String) = launch {
getWeekFoodDataUseCase(s)?.let{
_weekGetFoodArea.value = it.toWeekFoodResponse()
_weekGetFoodArea.emit(WeekFoodState.Loading)
getWeekFoodDataUseCase(s).collect {
when (it) {
is BaseResult.Success -> {
_weekGetFoodArea.emit(WeekFoodState.SuccessWeekFoodGetData(it.data))
}
is BaseResult.Error -> {
_weekGetFoodArea.emit(WeekFoodState.Error(it.errorCode))
}
}
}
}

fun postReview(requestReviewData: RequestReviewData) = launch {
postReviewDataUseCase(requestReviewData.toRequestReviewEntity())?.let{
Log.d("DebugTag", "postReviewDataUseCase result: $it")
_postReviewData.value = it.toResponseReviewData()
Log.d("DebugTag", "Value emitted to _postReviewData")
}
}

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
package com.myongsik.myongsikandroid.presentation.viewmodel.food

import com.myongsik.myongsikandroid.domain.model.food.ResponseWeekFoodEntity

sealed class WeekFoodState {

object UnInitialized : WeekFoodState()

object Loading : WeekFoodState()

data class SuccessWeekFoodGetData(val getWeekFoodData: ResponseWeekFoodEntity) : WeekFoodState()

data class Error(val errorCode: Int) : WeekFoodState()
}

0 comments on commit 85d43ee

Please sign in to comment.