-
Notifications
You must be signed in to change notification settings - Fork 0
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[FEAT] 4주차 과제 완료 #8
base: develop
Are you sure you want to change the base?
Changes from all commits
4c4a341
f1f4111
a531a0f
bb7f46f
6b6724f
9d9b3da
949c18d
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,40 @@ | ||
package org.sopt.and.api | ||
|
||
import com.jakewharton.retrofit2.converter.kotlinx.serialization.asConverterFactory | ||
import kotlinx.serialization.json.Json | ||
import okhttp3.MediaType.Companion.toMediaType | ||
import okhttp3.OkHttpClient | ||
import okhttp3.logging.HttpLoggingInterceptor | ||
import org.sopt.and.BuildConfig | ||
import org.sopt.and.api.service.HobbyService | ||
import org.sopt.and.api.service.LoginService | ||
import org.sopt.and.api.service.UserService | ||
import retrofit2.Retrofit | ||
|
||
object ApiFactory { | ||
private const val BASE_URL: String = BuildConfig.BASE_URL | ||
|
||
private val loggingInterceptor = HttpLoggingInterceptor().apply { | ||
level = HttpLoggingInterceptor.Level.BODY | ||
} | ||
|
||
private val client = OkHttpClient.Builder() | ||
.addInterceptor(loggingInterceptor) | ||
.build() | ||
|
||
val retrofit: Retrofit by lazy { | ||
Retrofit.Builder() | ||
.baseUrl(BASE_URL) | ||
.client(client) | ||
.addConverterFactory(Json.asConverterFactory("application/json".toMediaType())) | ||
.build() | ||
} | ||
|
||
inline fun <reified T> create(): T = retrofit.create(T::class.java) | ||
} | ||
|
||
object ServicePool { | ||
val userService = ApiFactory.create<UserService>() | ||
val loginService = ApiFactory.create<LoginService>() | ||
val hobbyService = ApiFactory.create<HobbyService>() | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,10 @@ | ||
package org.sopt.and.api.dto | ||
|
||
import kotlinx.serialization.SerialName | ||
import kotlinx.serialization.Serializable | ||
|
||
@Serializable | ||
data class ResponseErrorDto( | ||
@SerialName("code") | ||
val code: String | ||
) |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,16 @@ | ||
package org.sopt.and.api.dto | ||
|
||
import kotlinx.serialization.SerialName | ||
import kotlinx.serialization.Serializable | ||
|
||
@Serializable | ||
data class ResponseHobbySuccessDto( | ||
@SerialName("result") | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 다른 api들에서도 response가 result로 감싸져서 오기 때문에 BaseReposne를 만들어서 사용하는 것도 고려해보면 좋을 것 같아요! |
||
val result: HobbyData | ||
) | ||
|
||
@Serializable | ||
data class HobbyData( | ||
@SerialName("hobby") | ||
val hobby: String | ||
) |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,24 @@ | ||
package org.sopt.and.api.dto | ||
|
||
import kotlinx.serialization.SerialName | ||
import kotlinx.serialization.Serializable | ||
|
||
@Serializable | ||
data class ResponseLoginSuccessDto( | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. response와 request를 같은 파일에서 관리하시는데 저는 따로 파일을 만들었거든요!! 나중에 어떤게 더 좋을지 이야기해보는 것도 좋을 것 같네요😊 There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 분리하는게 더 좋을 것 같아요 ㅎㅎ .. 수정하겠습니다 ! |
||
@SerialName("result") | ||
val result: LoginData | ||
) | ||
|
||
@Serializable | ||
data class LoginData( | ||
@SerialName("token") | ||
val token: String | ||
) | ||
|
||
@Serializable | ||
data class RequestLoginDto( | ||
@SerialName("username") | ||
val username: String, | ||
@SerialName("password") | ||
val password: String | ||
) |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,26 @@ | ||
package org.sopt.and.api.dto | ||
|
||
import kotlinx.serialization.SerialName | ||
import kotlinx.serialization.Serializable | ||
|
||
@Serializable | ||
data class ResponseUserSuccessDto( | ||
@SerialName("result") | ||
val result: UserData | ||
) | ||
|
||
@Serializable | ||
data class UserData( | ||
@SerialName("no") | ||
val no: Int | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 더 직관적인 이름을 사용해도 좋을 것 같아요! There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 무조건 서버에서 내려오는 이름이랑 동일하게만 사용했었는데 .. 직관적인 네이밍을 해도 되는거였군요 ! 수정해보겠습니다 !! |
||
) | ||
|
||
@Serializable | ||
data class RequestUserDto( | ||
@SerialName("username") | ||
val username: String, | ||
@SerialName("password") | ||
val password: String, | ||
@SerialName("hobby") | ||
val hobby: String | ||
) |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,13 @@ | ||
package org.sopt.and.api.service | ||
|
||
import okhttp3.ResponseBody | ||
import retrofit2.Call | ||
import retrofit2.http.GET | ||
import retrofit2.http.Header | ||
|
||
interface HobbyService { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Service를 나누시는 기준이 무엇인지 궁금합니다. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 저는 보통 기능별로 나누는 편입니다 ! |
||
@GET("/user/my-hobby") | ||
fun getMyHobby( | ||
@Header("token") token: String | ||
): Call<ResponseBody> | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,14 @@ | ||
package org.sopt.and.api.service | ||
|
||
import okhttp3.ResponseBody | ||
import org.sopt.and.api.dto.RequestLoginDto | ||
import retrofit2.Call | ||
import retrofit2.http.Body | ||
import retrofit2.http.POST | ||
|
||
interface LoginService { | ||
@POST("/login") | ||
fun postLogin( | ||
@Body requestLogin: RequestLoginDto | ||
): Call<ResponseBody> | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,14 @@ | ||
package org.sopt.and.api.service | ||
|
||
import okhttp3.ResponseBody | ||
import org.sopt.and.api.dto.RequestUserDto | ||
import retrofit2.Call | ||
import retrofit2.http.Body | ||
import retrofit2.http.POST | ||
|
||
interface UserService { | ||
@POST("/user") | ||
fun postUser( | ||
@Body requestUser: RequestUserDto | ||
): Call<ResponseBody> | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -16,18 +16,19 @@ import androidx.navigation.compose.composable | |
import androidx.navigation.compose.currentBackStackEntryAsState | ||
import org.sopt.and.component.bar.BottomBar | ||
import org.sopt.and.ui.home.HomeScreen | ||
import org.sopt.and.ui.home.HomeViewModel | ||
import org.sopt.and.ui.my.MyScreen | ||
import org.sopt.and.ui.my.MyViewModel | ||
import org.sopt.and.ui.search.SearchScreen | ||
import org.sopt.and.ui.signin.SignInScreen | ||
import org.sopt.and.ui.signin.SignInViewModel | ||
import org.sopt.and.ui.signup.SignUpScreen | ||
import org.sopt.and.ui.signup.SignUpViewModel | ||
|
||
@Composable | ||
fun NavGraph(navController: NavHostController){ | ||
fun NavGraph(navController: NavHostController) { | ||
val signUpViewModel: SignUpViewModel = viewModel() | ||
val signInViewModel: SignInViewModel = viewModel() | ||
val myViewModel: MyViewModel = viewModel() | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 뷰모델을 navGraph에서 관리하시는 이유가 있나요? 각 뷰에서 관리하는게 더 좋을 것 같다는 생각이 드는데 혹시 다른 이유가 있으신지 궁금합니다! There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 전에 데이터를 넘기는 방법으로 한 뷰에서 두개의 viewmodel을 부른 적이 있었는데 그때 navgraph에서 뷰모델을 관리했었어요 ! 근데 이제 데이터를 넘기는 로직을 변경했으니 viewmodel 로직도 각 뷰에서 관리하는 방법으로 변경해야겠네요 감사합니다 !! |
||
|
||
val navBackStackEntry by navController.currentBackStackEntryAsState() | ||
val currentRoute = navBackStackEntry?.destination?.route | ||
|
@@ -37,7 +38,12 @@ fun NavGraph(navController: NavHostController){ | |
val selectedScreen = ScreenTab.entries.find { it.route == currentRoute } | ||
if (selectedScreen != null) { | ||
BottomBar(selected = selectedScreen, navController = navController) | ||
}else if (currentRoute in listOf(Routes.Home.route, Routes.My.route, Routes.Search.route)) { | ||
} else if (currentRoute in listOf( | ||
Routes.Home.route, | ||
Routes.My.route, | ||
Routes.Search.route | ||
) | ||
) { | ||
BottomBar(selected = null, navController = navController) | ||
} | ||
} | ||
|
@@ -49,9 +55,24 @@ fun NavGraph(navController: NavHostController){ | |
.padding(paddingValues) | ||
) { | ||
NavHost(navController = navController, startDestination = Routes.SignIn.route) { | ||
composable(Routes.SignIn.route) { SignInScreen(navController, signInViewModel = signInViewModel) } | ||
composable(Routes.SignUp.route) { SignUpScreen(navController, signUpViewModel = signUpViewModel) } | ||
composable(Routes.My.route) { MyScreen(navController, signInViewModel = signInViewModel) } | ||
composable(Routes.SignIn.route) { | ||
SignInScreen( | ||
navController, | ||
signInViewModel = signInViewModel | ||
) | ||
} | ||
composable(Routes.SignUp.route) { | ||
SignUpScreen( | ||
navController, | ||
signUpViewModel = signUpViewModel | ||
) | ||
} | ||
composable(Routes.My.route) { | ||
MyScreen( | ||
navController, | ||
myViewModel = myViewModel | ||
) | ||
} | ||
composable(Routes.Search.route) { SearchScreen(navController) } | ||
composable(Routes.Home.route) { HomeScreen(navController) } | ||
} | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
BASE_URL을 바로 사용하지 않고 value로 저장하신 이유가 무엇인가요?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
value로 저장하고 쓰는게 습관이 되어서 .. 보니까 저장 안하고도 쓸 수 있었군요 🥲
수정하겠습니다 !