Skip to content
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] WEEK4 - compose 필수과제 #9

Open
wants to merge 3 commits into
base: develop-compose
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
19 changes: 19 additions & 0 deletions app/build.gradle
Original file line number Diff line number Diff line change
@@ -1,7 +1,10 @@
plugins {
id 'com.android.application'
id 'org.jetbrains.kotlin.android'
id 'org.jetbrains.kotlin.plugin.serialization' version '1.9.0'
}
Properties properties = new Properties()
properties.load(project.rootProject.file('local.properties').newDataInputStream())

android {
namespace 'com.sopt.now.compose'
Expand All @@ -18,6 +21,8 @@ android {
vectorDrawables {
useSupportLibrary true
}

buildConfigField "String", "AUTH_BASE_URL", properties["base.url"]
}

buildTypes {
Expand All @@ -35,6 +40,7 @@ android {
}
buildFeatures {
compose true
buildConfig true
}
composeOptions {
kotlinCompilerExtensionVersion '1.5.1'
Expand Down Expand Up @@ -63,4 +69,17 @@ dependencies {
androidTestImplementation 'androidx.compose.ui:ui-test-junit4'
debugImplementation 'androidx.compose.ui:ui-tooling'
debugImplementation 'androidx.compose.ui:ui-test-manifest'

implementation 'com.squareup.retrofit2:retrofit:2.9.0'
implementation 'org.jetbrains.kotlinx:kotlinx-serialization-json:1.4.1'
implementation 'com.squareup.retrofit2:converter-gson:2.9.0'
implementation 'com.jakewharton.retrofit:retrofit2-kotlinx-serialization-converter:1.0.0'

// define a BOM and its version
implementation(platform("com.squareup.okhttp3:okhttp-bom:4.10.0"))

// define any required OkHttp artifacts without version
implementation("com.squareup.okhttp3:okhttp")
implementation("com.squareup.okhttp3:okhttp:4.9.1")
implementation("com.squareup.okhttp3:logging-interceptor")
}
5 changes: 3 additions & 2 deletions app/src/main/AndroidManifest.xml
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,10 @@
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools">

<uses-permission android:name="android.permission.INTERNET" />
<application
android:allowBackup="true"
android:usesCleartextTraffic="true"
android:dataExtractionRules="@xml/data_extraction_rules"
android:fullBackupContent="@xml/backup_rules"
android:icon="@mipmap/ic_launcher"
Expand All @@ -19,7 +21,6 @@
android:theme="@style/Theme.NOWSOPTAndroid">
<intent-filter>
<action android:name="android.intent.action.MAIN" />

<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
Expand All @@ -29,7 +30,7 @@
android:label="@string/app_name"
android:theme="@style/Theme.NOWSOPTAndroid" />
<activity
android:name=".activity.SignupActivity"
android:name=".activity.SignUpActivity"
android:exported="false"
android:label="@string/app_name"
android:theme="@style/Theme.NOWSOPTAndroid" />
Expand Down
22 changes: 22 additions & 0 deletions app/src/main/java/com/sopt/now/compose/ApiFactory.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
package com.sopt.now.compose

import com.jakewharton.retrofit2.converter.kotlinx.serialization.asConverterFactory
import kotlinx.serialization.json.Json
import okhttp3.MediaType.Companion.toMediaType
import retrofit2.Retrofit
object ApiFactory {
private const val BASE_URL: String = BuildConfig.AUTH_BASE_URL

val retrofit: Retrofit by lazy {
Retrofit.Builder()
.baseUrl(BASE_URL)
.addConverterFactory(Json.asConverterFactory("application/json".toMediaType()))
.build()
}

inline fun <reified T> create(): T = retrofit.create(T::class.java)
}

object ServicePool {
val authService = ApiFactory.create<AuthService>()
}
28 changes: 28 additions & 0 deletions app/src/main/java/com/sopt/now/compose/AuthService.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
package com.sopt.now.compose

import com.sopt.now.compose.Dto.RequestLoginDto
import com.sopt.now.compose.Dto.RequestSignUpDto
import com.sopt.now.compose.Dto.ResponseLoginDto
import com.sopt.now.compose.Dto.ResponseSignUpDto
import com.sopt.now.compose.Dto.ResponseUserInfoDto
import retrofit2.Call
import retrofit2.http.Body
import retrofit2.http.GET
import retrofit2.http.Header
import retrofit2.http.POST
interface AuthService {
@POST("member/join")
fun signUp(
@Body request: RequestSignUpDto,
): Call<ResponseSignUpDto>

@POST("member/login")
fun login(
@Body request: RequestLoginDto
): Call<ResponseLoginDto>

@GET("member/info")
fun getUserInfo(
@Header("memberid") memberId: String
): Call<ResponseUserInfoDto>
}
12 changes: 12 additions & 0 deletions app/src/main/java/com/sopt/now/compose/Dto/RequestLoginDto.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
package com.sopt.now.compose.Dto

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

@Serializable
data class RequestLoginDto(
@SerialName("authenticationId")
val authenticationId: String,
@SerialName("password")
val password: String
)
16 changes: 16 additions & 0 deletions app/src/main/java/com/sopt/now/compose/Dto/RequestSignUpDto.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
package com.sopt.now.compose.Dto

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

@Serializable
data class RequestSignUpDto(
@SerialName("authenticationId")
val authenticationId: String,
@SerialName("password")
val password: String,
@SerialName("nickname")
val nickname: String,
@SerialName("phone")
val phone: String,
)
12 changes: 12 additions & 0 deletions app/src/main/java/com/sopt/now/compose/Dto/ResponseLoginDto.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
package com.sopt.now.compose.Dto

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

@Serializable
data class ResponseLoginDto(
@SerialName("code")
val code: Int,
@SerialName("message")
val message: String,
)
12 changes: 12 additions & 0 deletions app/src/main/java/com/sopt/now/compose/Dto/ResponseSignUpDto.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
package com.sopt.now.compose.Dto

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

@Serializable
data class ResponseSignUpDto(
@SerialName("code")
val code: Int,
@SerialName("message")
val message: String,
)
24 changes: 24 additions & 0 deletions app/src/main/java/com/sopt/now/compose/Dto/ResponseUserInfoDto.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
package com.sopt.now.compose.Dto

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

@Serializable
data class ResponseUserInfoDto(
@SerialName("code")
val code: Int,
@SerialName("message")
val message: String,
@SerialName("data")
val data: UserData,
)

@Serializable
data class UserData(
@SerialName("authenticationId")
val authenticationId: String,
@SerialName("nickname")
val nickname: String,
@SerialName("phone")
val phone: String,
)
Original file line number Diff line number Diff line change
Expand Up @@ -15,14 +15,13 @@ sealed class HomeData {
data class UserInfoData(val userInfo: UserInfo) : HomeData()
data class FriendData(val friend: Friend) : HomeData()
}

val homeDataList = listOf<HomeData>(
HomeData.UserInfoData(
userInfo = UserInfo(
id = "nagaeng",
password = "qazwsx!@#",
nickname = "이나경",
mbti = "ENTJ"
phone = "010-3412-1683"
)
),
HomeData.FriendData(
Expand Down Expand Up @@ -112,5 +111,4 @@ fun HomeView(homeDataList: List<HomeData>) {
}
}
}
}

}
117 changes: 117 additions & 0 deletions app/src/main/java/com/sopt/now/compose/MypageScreen.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,117 @@
package com.sopt.now.compose

import android.content.Context
import android.util.Log
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.Spacer
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.height
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.width
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.runtime.LaunchedEffect
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.runtime.setValue
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.text.font.FontWeight
import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.sp
import com.sopt.now.compose.Dto.ResponseUserInfoDto
import com.sopt.now.compose.user.UserInfo
import retrofit2.Call
import retrofit2.Callback
import retrofit2.Response
import kotlin.coroutines.resume
import kotlin.coroutines.resumeWithException
import kotlin.coroutines.suspendCoroutine
@Composable
fun MyPageFragment(context: Context, userId: String) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

컴포저블 함수에 직접 Context를 매개변수로 전달하는 것은 권장하지 않는 것으로 알고있는데 어떤 방법이 있을까요?

var userInfo by remember { mutableStateOf<UserInfo?>(null) }

LaunchedEffect(userId) {
try {
userInfo = getUserInfo(userId)
} catch (e: Exception) {
Comment on lines +37 to +40
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

단순 궁금증인데 userId를 매개변수로 받아서 LaunchedEffect에 넣어주는 것만으로도 getUserInfo() 함수가 실행이 되나요,,?!

Log.e("MyPageFragment", "Error: ${e.message}")
}
}

userInfo?.let { user ->
Column(
modifier = Modifier
.fillMaxSize()
.padding(horizontal = 30.dp, vertical = 10.dp)
) {
Column(
modifier = Modifier
.fillMaxWidth()
.padding(10.dp),
horizontalAlignment = Alignment.CenterHorizontally,
) {
Spacer(modifier = Modifier.width(20.dp))
Text(
text = user.nickname,
fontSize = 20.sp,
fontWeight = FontWeight.Bold,
)
Spacer(modifier = Modifier.height(20.dp))
Text(
text = "ID",
fontSize = 25.sp
)
Text(
text = user.id,
fontSize = 20.sp,
color = Color.Gray
)
Spacer(modifier = Modifier.height(20.dp))
Text(
text = "Phone",
fontSize = 25.sp
)
Text(
text = user.phone,
fontSize = 20.sp,
color = Color.Gray
)
}
}
}
}

suspend fun getUserInfo(userId: String): UserInfo {
return suspendCoroutine { continuation ->
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

suspendCoroutine을 사용하신 이유가 있나요? 그냥 궁금!!

ServicePool.authService.getUserInfo(userId).enqueue(object : Callback<ResponseUserInfoDto> {
override fun onResponse(
call: Call<ResponseUserInfoDto>,
response: Response<ResponseUserInfoDto>,
) {
if (response.isSuccessful) {
val data: ResponseUserInfoDto? = response.body()
data?.let {
continuation.resume(
Comment on lines +97 to +98
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

resume은 어떤 역할을 하는 건가용..? 궁금해서 물어봅니당

UserInfo(
it.data.authenticationId,
"",
it.data.nickname,
it.data.phone
)
)
}
} else {
continuation.resumeWithException(Exception("Failed to fetch user info"))
}
}

override fun onFailure(call: Call<ResponseUserInfoDto>, t: Throwable) {
continuation.resumeWithException(t)
}
})
}
}
Loading