Skip to content

Commit

Permalink
[refactor] #9 getMyHobby관련 clean architecture 적용
Browse files Browse the repository at this point in the history
  • Loading branch information
kamja0510 committed Dec 5, 2024
1 parent a1a8df0 commit 731b2c1
Show file tree
Hide file tree
Showing 24 changed files with 132 additions and 45 deletions.
2 changes: 1 addition & 1 deletion app/src/main/java/org/sopt/and/MainActivity.kt
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,8 @@ package org.sopt.and
import android.os.Bundle
import androidx.activity.ComponentActivity
import androidx.activity.compose.setContent
import org.sopt.and.data.service.AppContext
import org.sopt.and.presentation.navigation.Navigation
import org.sopt.and.services.AppContext
import org.sopt.and.ui.theme.ANDANDROIDTheme

class MainActivity : ComponentActivity() {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
package org.sopt.and.data.datasource

import org.sopt.and.data.model.response.GetMyHobbyResponseDto
import org.sopt.and.data.service.UserService

class GetMyHobbyDataSource(
private val userService: UserService
) {
suspend fun getMyHobby(): GetMyHobbyResponseDto = userService.getMyHobby()
}
9 changes: 9 additions & 0 deletions app/src/main/java/org/sopt/and/data/mapper/Mapper.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
package org.sopt.and.data.mapper

import org.sopt.and.data.model.response.GetMyHobbyResponseResultDto
import org.sopt.and.domain.model.MyHobbyEntity

object Mapper {
fun toMyHobbyEntity(getHobbyResponseResultDto: GetMyHobbyResponseResultDto) =
MyHobbyEntity(myHobby = getHobbyResponseResultDto.myHobby)
}

This file was deleted.

Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
package org.sopt.and.data.model.response

import kotlinx.serialization.SerialName
import kotlinx.serialization.Serializable

@Serializable
data class GetMyHobbyResponseDto(
val result: GetMyHobbyResponseResultDto? = null,
val code: String? = null
)

@Serializable
data class GetMyHobbyResponseResultDto(
@SerialName("hobby")
val myHobby: String
)
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
package org.sopt.and.data.repositoryimpl

import org.sopt.and.data.datasource.GetMyHobbyDataSource
import org.sopt.and.data.mapper.Mapper
import org.sopt.and.domain.model.MyHobbyEntity
import org.sopt.and.domain.repository.GetMyHobbyRepository

class GetMyHobbyRepositoryImpl(
private val getMyHobbyDataSource: GetMyHobbyDataSource
) : GetMyHobbyRepository {
override suspend fun getMyHobby(): Result<MyHobbyEntity> =
runCatching {
getMyHobbyDataSource.getMyHobby().result?.let { Mapper.toMyHobbyEntity(it) }!!
}
}
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
package org.sopt.and.services
package org.sopt.and.data.service

import com.jakewharton.retrofit2.converter.kotlinx.serialization.asConverterFactory
import kotlinx.serialization.json.Json
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
package org.sopt.and.services
package org.sopt.and.data.service

import android.content.Context

Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
package org.sopt.and.services
package org.sopt.and.data.service

import android.content.Context
import kotlinx.coroutines.flow.first
Expand Down
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
package org.sopt.and.services
package org.sopt.and.data.service

import android.content.Context
import androidx.datastore.preferences.core.edit
import androidx.datastore.preferences.core.stringPreferencesKey
import androidx.datastore.preferences.preferencesDataStore
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.map
import org.sopt.and.services.TokenManager.Companion.DATASTORE_NAME
import org.sopt.and.data.service.TokenManager.Companion.DATASTORE_NAME

val Context.dataStore by preferencesDataStore(DATASTORE_NAME)

Expand Down
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
package org.sopt.and.services
package org.sopt.and.data.service

import org.sopt.and.data.model.request.SignInRequestDto
import org.sopt.and.data.model.request.SignUpRequestDto
import org.sopt.and.data.model.response.GetHobbyResponseDto
import org.sopt.and.data.model.response.GetMyHobbyResponseDto
import org.sopt.and.data.model.response.SignInResponseDto
import org.sopt.and.data.model.response.SignUpResponseDto
import retrofit2.Response
Expand All @@ -18,5 +18,5 @@ interface UserService {
suspend fun signIn(@Body request: SignInRequestDto): Response<SignInResponseDto>

@GET("/user/my-hobby")
suspend fun getMyHobby(): GetHobbyResponseDto
suspend fun getMyHobby(): GetMyHobbyResponseDto
}
Original file line number Diff line number Diff line change
@@ -1,7 +1,20 @@
package org.sopt.and.domain.repository

import org.sopt.and.data.datasource.GetMyHobbyDataSource
import org.sopt.and.data.repositoryimpl.GetMyHobbyRepositoryImpl
import org.sopt.and.data.service.ServicePool
import org.sopt.and.domain.model.MyHobbyEntity

interface GetMyHobbyRepository {
suspend fun getMyHobby(): Result<MyHobbyEntity>

companion object {
fun create(): GetMyHobbyRepositoryImpl {
return GetMyHobbyRepositoryImpl(
GetMyHobbyDataSource(
ServicePool.userService
)
)
}
}
}
11 changes: 11 additions & 0 deletions app/src/main/java/org/sopt/and/domain/usecase/GetMyHobbyUseCase.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
package org.sopt.and.domain.usecase

import org.sopt.and.domain.model.MyHobbyEntity
import org.sopt.and.domain.repository.GetMyHobbyRepository

class GetMyHobbyUseCase(
private val getMyHobbyRepository: GetMyHobbyRepository
) {
suspend operator fun invoke(): Result<MyHobbyEntity> =
getMyHobbyRepository.getMyHobby()
}
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ import androidx.compose.ui.tooling.preview.Preview
import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.sp
import org.sopt.and.R
import org.sopt.and.WavveUtils
import org.sopt.and.presentation.util.WavveUtils
import org.sopt.and.ui.theme.ANDANDROIDTheme
import org.sopt.and.ui.theme.Grey200

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,12 +6,13 @@ import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.StateFlow
import kotlinx.coroutines.flow.asStateFlow
import kotlinx.coroutines.launch
import org.sopt.and.data.model.response.GetHobbyResponseDto
import org.sopt.and.services.ServicePool

class MyInfoViewModel : ViewModel() {
private val userService by lazy { ServicePool.userService }
import org.sopt.and.domain.model.MyHobbyEntity
import org.sopt.and.domain.usecase.GetMyHobbyUseCase

class MyInfoViewModel(
private val getMyHobbyUseCase: GetMyHobbyUseCase
) : ViewModel() {

private val _uiState = MutableStateFlow(MyInfoUiState())
val uiState: StateFlow<MyInfoUiState> = _uiState.asStateFlow()

Expand All @@ -21,10 +22,8 @@ class MyInfoViewModel : ViewModel() {

fun getMyHobby() {
viewModelScope.launch {
runCatching {
userService.getMyHobby()
}.onSuccess { response: GetHobbyResponseDto ->
response.result?.let { setMyHobby(it.hobby) }
getMyHobbyUseCase().onSuccess { myHobbyEntity: MyHobbyEntity ->
setMyHobby(myHobbyEntity.myHobby)
}.onFailure { }
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ import org.sopt.and.presentation.myinfo.MyInfoViewModel
import org.sopt.and.presentation.search.SearchScreen
import org.sopt.and.presentation.signin.SignInScreen
import org.sopt.and.presentation.signup.SignUpScreen
import org.sopt.and.presentation.viewmodelfactory.MyInfoViewModelFactory

@Composable
fun Navigation(
Expand All @@ -25,7 +26,9 @@ fun Navigation(
val navigationUiState by navigationViewModel.uiState.collectAsStateWithLifecycle()
val navController = rememberNavController()

val myInfoViewModel = viewModel<MyInfoViewModel>()
val myInfoViewModel: MyInfoViewModel = viewModel(
factory = MyInfoViewModelFactory()
)
val myInfoUiState by myInfoViewModel.uiState.collectAsStateWithLifecycle()

Scaffold(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import androidx.compose.material.icons.filled.AccountCircle
import androidx.compose.material.icons.filled.Home
import androidx.compose.material.icons.filled.Search
import org.sopt.and.R
import org.sopt.and.WavveUtils
import org.sopt.and.presentation.util.WavveUtils

data class NavigationUiState(
val isBottomNavigationVisible: Boolean = false,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,12 +11,12 @@ import kotlinx.coroutines.flow.asStateFlow
import kotlinx.coroutines.launch
import kotlinx.serialization.json.Json
import org.sopt.and.R
import org.sopt.and.WavveUtils.showSnackbar
import org.sopt.and.data.model.request.SignInRequestDto
import org.sopt.and.data.model.response.SignInResponseDto
import org.sopt.and.services.AppContext
import org.sopt.and.services.ServicePool
import org.sopt.and.services.TokenManager
import org.sopt.and.data.service.AppContext
import org.sopt.and.data.service.ServicePool
import org.sopt.and.data.service.TokenManager
import org.sopt.and.presentation.util.WavveUtils.showSnackbar
import retrofit2.Response

class SignInViewModel : ViewModel() {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,9 @@ package org.sopt.and.presentation.signin.components

import androidx.compose.runtime.Composable
import org.sopt.and.R
import org.sopt.and.WavveUtils.transformationPasswordVisual
import org.sopt.and.presentation.components.ShowOrHideToggle
import org.sopt.and.presentation.components.SignInOrSignUpTextField
import org.sopt.and.presentation.util.WavveUtils.transformationPasswordVisual

@Composable
fun SignInPasswordField(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,10 +9,10 @@ import kotlinx.coroutines.flow.asStateFlow
import kotlinx.coroutines.launch
import kotlinx.serialization.json.Json
import org.sopt.and.R
import org.sopt.and.WavveUtils.showToast
import org.sopt.and.data.model.request.SignUpRequestDto
import org.sopt.and.data.model.response.SignUpResponseDto
import org.sopt.and.services.ServicePool
import org.sopt.and.data.service.ServicePool
import org.sopt.and.presentation.util.WavveUtils.showToast


class SignUpViewModel : ViewModel() {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ import androidx.compose.ui.text.style.LineHeightStyle
import androidx.compose.ui.unit.em
import androidx.compose.ui.unit.sp
import org.sopt.and.R
import org.sopt.and.WavveUtils
import org.sopt.and.presentation.util.WavveUtils
import org.sopt.and.ui.theme.Grey200
import org.sopt.and.ui.theme.White100

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,10 +7,10 @@ import androidx.compose.runtime.Composable
import androidx.compose.ui.Modifier
import androidx.compose.ui.unit.dp
import org.sopt.and.R
import org.sopt.and.WavveUtils.transformationPasswordVisual
import org.sopt.and.presentation.components.CautionBox
import org.sopt.and.presentation.components.ShowOrHideToggle
import org.sopt.and.presentation.components.SignInOrSignUpTextField
import org.sopt.and.presentation.util.WavveUtils.transformationPasswordVisual

@Composable
fun SignUpPasswordField(
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
package org.sopt.and
package org.sopt.and.presentation.util

import android.content.Context
import android.widget.Toast
Expand All @@ -8,6 +8,7 @@ import androidx.compose.ui.text.input.PasswordVisualTransformation
import androidx.compose.ui.text.input.VisualTransformation
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.launch
import org.sopt.and.R

object WavveUtils {
const val MIN_PASSWORD_LENGTH = 8
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
package org.sopt.and.presentation.viewmodelfactory

import androidx.lifecycle.ViewModel
import androidx.lifecycle.ViewModelProvider
import org.sopt.and.domain.repository.GetMyHobbyRepository
import org.sopt.and.domain.usecase.GetMyHobbyUseCase
import org.sopt.and.presentation.myinfo.MyInfoViewModel

class MyInfoViewModelFactory() : ViewModelProvider.Factory {
override fun <T : ViewModel> create(modelClass: Class<T>): T {
return when (modelClass) {

MyInfoViewModel::class.java -> {
MyInfoViewModel(
GetMyHobbyUseCase(
getMyHobbyRepository = GetMyHobbyRepository.create()
)
) as T
}

else -> throw IllegalArgumentException("Unknown ViewModel Class")
}
}
}

0 comments on commit 731b2c1

Please sign in to comment.