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/week xml 06 #11

Open
wants to merge 16 commits into
base: develop-xml
Choose a base branch
from
Open

Feat/week xml 06 #11

wants to merge 16 commits into from

Conversation

hyoeunjoo
Copy link
Collaborator

πŸ“Œπ˜π˜΄π˜΄π˜Άπ˜¦π˜΄

  • closed #

πŸ“Žπ˜žπ˜°π˜³π˜¬ π˜‹π˜¦π˜΄π˜€π˜³π˜ͺ𝘱𝘡π˜ͺ𝘰𝘯

  • μƒˆλ‘­κ²Œ 폴더링
  • 코루틴 μ‚¬μš©
  • ViewModel둜 뢄리

πŸ“·π˜šπ˜€π˜³π˜¦π˜¦π˜―π˜΄π˜©π˜°π˜΅

week06.mp4

πŸ’¬π˜›π˜° π˜™π˜¦π˜·π˜ͺ𝘦𝘸𝘦𝘳𝘴

@hyoeunjoo hyoeunjoo self-assigned this May 24, 2024
Copy link
Member

@chanubc chanubc left a comment

Choose a reason for hiding this comment

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

μ–Έμ œ μ΄λ ‡κ²Œ μ„±μž₯ν•˜μ…¨μ£ ?
μ§„μ§œ μž˜ν•˜μ‹œλ„€μš”γ„·γ„·

Comment on lines 10 to 33
class AuthRepoImpl(
private val authService: AuthService,
) : AuthRepository {
override suspend fun logIn(authData: AuthData): Result<Response<Unit>> = runCatching {
authService.logIn(
request = RequestLogInDto(
authenticationId = authData.id,
password = authData.pw
)
)
}
override suspend fun signUp(authData: AuthData): Result<Response<Unit>> = runCatching {
authService.signUp(
RequestSignUpDto(
authenticationId = authData.id,
password = authData.pw,
nickname = authData.name ?: "",
phone = authData.phone ?: ""
)
)
}


}
Copy link
Member

Choose a reason for hiding this comment

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

와 μ§„μ§œ 폼 λ―Έμ³€λ„€μš”γ„·γ„·

Comment on lines +14 to +16
val loggingInterceptor = HttpLoggingInterceptor().apply {
level = HttpLoggingInterceptor.Level.BODY
}
Copy link
Member

Choose a reason for hiding this comment

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

loggingInterceptor λ‹¬μ•„λ³΄μ…¨μœΌλ©΄ HeaderInterceptor도 ν•΄λ³΄μ‹œλŠ”κ±° μΆ”μ²œλ“œλ¦½λ‹ˆλ‹€γ…Žγ…Ž

Comment on lines 6 to 9
interface AuthRepository {
suspend fun logIn(authData: AuthData): Result<Response<Unit>>
suspend fun signUp(authData: AuthData): Result<Response<Unit>>
}
Copy link
Member

Choose a reason for hiding this comment

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

μ•„λ‹ˆ μ΄μ‚¬λžŒ 뭐야?


import android.provider.ContactsContract.CommonDataKinds.Phone

data class AuthData(
Copy link
Member

@chanubc chanubc May 25, 2024

Choose a reason for hiding this comment

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

Suggested change
data class AuthData(
data class AuthEntity(

domain μ˜μ—­μ˜ data classλŠ” 보톡 Entity둜 넀이밍 μ§€μ–΄μš”

각 μ˜μ—­λ³„ 넀이밍(보톡 μ΄λ ‡κ²Œ μ§€μ–΄μš”)

  1. ui : model
  2. domain : entity
  3. data : dto

class LoginViewModel(
private val authRepository: AuthRepository
) : ViewModel() {
val loginResult: MutableLiveData<Boolean> = MutableLiveData()
Copy link
Member

Choose a reason for hiding this comment

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

Suggested change
val loginResult: MutableLiveData<Boolean> = MutableLiveData()
private val _loginResult: MutableLiveData<Boolean> = MutableLiveData()
val loginResult: LiveData<Boolean> get() = _loginResult

그런데 μ—¬κΈ°μ„œ μˆ˜μ •ν•΄μ•Ό ν•  뢀뢄이 ν•˜λ‚˜ 더 μ‘΄μž¬ν•©λ‹ˆλ‹€. λ°”λ‘œ MutableLiveDataλ₯Ό κ΅¬λ…ν•˜λŠ” λΆ€λΆ„μΈλ°μš”, Kotlinμ—μ„œλŠ” 기본적으둜 λΆˆλ³€μ„±μ„ 지ν–₯ν•©λ‹ˆλ‹€. ViewModel λ‚΄μ—μ„œλŠ” μ„œλ²„ν†΅μ‹  λ“±μ˜ λ°œν–‰κ°μ²΄μ˜ λ‚΄λΆ€ μƒνƒœλ₯Ό λ³€κ²½ν•΄μ•Όν•˜λŠ” 일이 μžˆμ§€λ§Œ, μ™ΈλΆ€ 객체(Activity, Fragment)μ—μ„œλŠ” 이λ₯Ό λ³€κ²½ν•  μ΄μœ λ„ μ—†κ³  였히렀 λ³€κ²½ν•œλ‹€λ©΄ μ˜ˆμƒμΉ˜ λͺ»ν•œ 일듀(SideEffect)이 λ°œμƒν•  μˆ˜λ„ μžˆμŠ΅λ‹ˆλ‹€.

λ”°λΌμ„œ 이런 λ°œν–‰κ°μ²΄λ₯Ό μ‚¬μš©ν•˜λŠ” 경우 μƒνƒœλ₯Ό λ³€κ²½ν•  수 μžˆλŠ” κ°μ²΄λŠ” private으둜, μƒνƒœλ₯Ό κ³΅κ°œν•˜λŠ” κ°μ²΄λŠ” λΆˆλ³€κ°μ²΄λ‘œ κ³΅κ°œν•΄μ•Όν•©λ‹ˆλ‹€. 이런 기법을 **Backing Property**라고 ν•©λ‹ˆλ‹€.

μΆ”κ°€λ‘œ get() = λ₯Ό μ‚¬μš©ν•˜μ§€ μ•Šκ³  = 으둜 값을 λ°”λ‘œ ν• λ‹Ήν•˜λŠ” 방법이 μžˆλŠ”λ° 두 μ½”λ“œμ˜ 차이점이 무엇인지 찾아보고 λŒ“κΈ€λ‘œ λ‚¨κ²¨μ£Όμ„Έμš”!

    val loginResult: LiveData<Boolean> get() = _loginResult
    val loginResult: LiveData<Boolean> = _loginResult

Copy link
Member

Choose a reason for hiding this comment

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

λ‚΄λΆ€μ—μ„œ 값을 λ³€κ²½ν• λ•ŒλŠ” _loginResult.value = κ°’
μ΄λŸ°μ‹μœΌλ‘œ μ‚¬μš©ν•˜μ‹œλ©΄ λ©λ‹ˆλ‹€!

μ™ΈλΆ€μ—μ„œλŠ” loginResultλ₯Ό μ‚¬μš©ν•˜κ΅¬μš”!

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

val loginResult: LiveData get() = _loginResult λ₯Ό μ‚¬μš©ν•˜λ©΄ _loginResultκ°€ λ³€κ²½λ λ•Œλ§ˆλ‹€ loginResult에 λ³€κ²½λœ 값을 λ„£μ–΄μ€λ‹ˆλ‹€. λ™μ μœΌλ‘œ 값을 κ°€μ Έμ˜¬ 수 μžˆλ‹€λŠ” μž₯점이 μžˆμŠ΅λ‹ˆλ‹€.

val loginResult: LiveData = _loginResult
_loginResult의 값을 μ΄ˆκΈ°ν™” μ‹œμ μ— loginResult에 ν• λ‹Ήν•©λ‹ˆλ‹€.

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

[MutableLiveData]
LiveDataλŠ” Observer νŒ¨ν„΄μ„ λ”°λ₯΄λ©° λ°μ΄ν„°μ˜ 변경이 일어날 λ•Œλ§ˆλ‹€ μ½œλ°±μ„ λ°›μŠ΅λ‹ˆλ‹€.
μ΄λ•Œ, LiveData의 값을 λ³€κ²½ν•˜κ²Œ ν•΄μ£ΌλŠ” ν•¨μˆ˜λŠ” setValue와 postValueκ°€ μžˆμŠ΅λ‹ˆλ‹€.
두 ν•¨μˆ˜λŠ” protected둜 λ˜μ–΄μžˆκΈ°μ—, μ™ΈλΆ€μ—μ„œ 값을 λ³€κ²½ν•΄μ£ΌκΈ° μœ„ν•΄μ„œλŠ” LiveDataλ₯Ό μƒμ†λ°›λŠ” MutableLiveDataλ₯Ό μ‚¬μš©ν•΄μ•Ό ν•©λ‹ˆλ‹€.

                [email protected] =it
                loginResult.value = true

backing propertyλ₯Ό μ‚¬μš©ν•˜μ—¬ loginResultλ₯Ό λ°”κΎΈλ‹ˆ μœ„μ˜ 뢀뢄에 λ¬Έμ œκ°€ μƒκ²ΌμŠ΅λ‹ˆλ‹€.
MutableLiveData의 valueλŠ” 메인 μŠ€λ ˆλ“œμ—μ„œλ§Œ μ‚¬μš©ν•  수 μžˆμœΌλ―€λ‘œ λ°±κ·ΈλΌμš΄λ“œμ—μ„œ μ•ˆμ „ν•˜κ²Œ 값을 보낼 수 μžˆλŠ” postValueλ₯Ό μ‚¬μš©ν•©λ‹ˆλ‹€.

private val authRepository: AuthRepository
) : ViewModel() {
val loginResult: MutableLiveData<Boolean> = MutableLiveData()
val errorMessage: MutableLiveData<String> = MutableLiveData()
Copy link
Member

Choose a reason for hiding this comment

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

또 Uistateλ₯Ό μ‚¬μš©ν•˜κ²Œ 되면 loginResult와 errorMesage의 λ³€μˆ˜λ₯Ό ν•©μ³μ„œ μ‚¬μš© κ°€λŠ₯ν•©λ‹ˆλ‹€!

sealed class LoginState {
    data object Loading : LoginState()
    data class Success(val data: AuthData) : LoginState()
    data class Failure(val errorMessage: String) : LoginState()
}

ν•΄λ‹Ή seale classλ₯Ό λ§Œλ“€κ³  LiveData의 νŒŒλΌλ―Έν„°μ—

    private val _loginResult: MutableLiveData<LoginState<Boolean>> = MutableLiveData()
    val loginResult: LiveData<LoginState<Boolean>> get() = _loginResult

앑티비티에선 observeν•˜κ³  각 stateλ₯Ό when절둜 λΆ„κΈ°μ²˜λ¦¬ ν›„ isλ₯Ό 톡해 smart castν•œ λ‹€μŒ, 각 state(success, fail) λ“±λ“± ν•„μš”ν•œ μž‘μ—…μ„ ν•˜λ©΄ λ©λ‹ˆλ‹€

μ΄λŸ°μ‹μœΌλ‘œ μ„ μ–Έν•΄μ„œ μ‚¬μš©ν•˜μ‹œλ©΄ λ©λ‹ˆλ‹€! μžμ„Έν•œ 사항듀은 uistate에 λŒ€ν•΄μ„œ μ•Œμ•„λ³΄λ©΄ 쒋을것 κ°™μ•„μš”!

Comment on lines +8 to +18
class LoginViewModelFactory : ViewModelProvider.Factory{
override fun <T : ViewModel> create(modelClass: Class<T>): T {
if (modelClass.isAssignableFrom(LoginViewModel::class.java)) { //modelClassκ°€ LoginViewModel인지 확인
val repository =
AuthRepoImpl(ServicePool.authService)//authServiceλ₯Ό 인자둜 λ°›μ•„μ„œ RepositoryμΈμŠ€ν„΄μŠ€ 생성
return LoginViewModel(repository) as T
} else {
throw IllegalArgumentException("Failed to create ViewModel: ${modelClass.name}")
}
}
}
Copy link
Member

Choose a reason for hiding this comment

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

μ•„λ‹ˆ 이거 μ–΄λ””μ„œ λ°°μš°μ…¨μ£ ?γ„·γ„·

Copy link
Member

Choose a reason for hiding this comment

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

이게 μ œκ°€ λ§μ”€λ“œλ Έλ˜ μ˜μ‘΄μ„± μˆ˜λ™ μ£Όμž…μž…λ‹ˆλ‹€!

Copy link
Member

Choose a reason for hiding this comment

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

λ·°λͺ¨λΈ νŽ™ν† λ¦¬κΉŒμ§€...γ„·γ„·

Comment on lines 8 to 18
import androidx.lifecycle.Observer
import androidx.lifecycle.ViewModelProvider
import com.sopt.now.R
import com.sopt.now.databinding.ActivitySignupBinding
import com.sopt.now.dto.SignUp.RequestSignUpDto
import com.sopt.now.domain.model.AuthData
import com.sopt.now.presentation.Login.LoginActivity
import com.sopt.now.presentation.User.SignUpViewModelFactory


class SignUpActivity : AppCompatActivity() {
private lateinit var binding: ActivitySignupBinding
private lateinit var viewModel: SignUpViewModel
private val viewModel: SignUpViewModel by viewModels { SignUpViewModelFactory() }
Copy link
Member

Choose a reason for hiding this comment

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

μ‚¬μš©λ„ μ •ν™•ν•˜λ„€μš―

Comment on lines +33 to +37
val error = response.errorBody()?.string()
val jsonObject = error?.let { JSONObject(it) }

val message = jsonObject?.getString("message")
errorMessage.postValue(message.toString())
Copy link
Member

Choose a reason for hiding this comment

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

json νŒŒμ‹± μ’‹μŠ΅λ‹ˆλ‹€! μ΄λŸ¬ν•œ jsonνŒŒμ‹±λ„ dataμ˜μ—­μ—μ„œ ν•˜λ©΄ μ’‹κ² μ£ ?

-tmi μ•ˆλ΄λ„ 됨-
λ˜ν•œ μ„œλ²„ 응닡 μ‹€νŒ¨μ‹œ, λ‚΄ μ˜ˆμƒλŒ€λ‘œ jsonν˜•νƒœλ‘œ μ˜€μ§€ μ•ŠλŠ” κ²½μš°λ„ μžˆμŠ΅λ‹ˆλ‹€! (ex. λ©€ν‹°νŒŒνŠΈ-이미지 전솑)
이런 경우 μ•žμ„œ λ§μ”€λ“œλ¦° json νŒŒμ‹± 였λ₯˜κ°€ λ‚˜κ² μ£ ? μ΄λŸ¬ν•œ 였λ₯˜λ„ throwκ°€λŠ₯ν•©λ‹ˆλ‹€! 개발자 μž…μž₯μ—μ„œλŠ” error handling이 μš©μ΄ν•΄μ§€μ£ (λ¬Όλ‘  이런건 μ‚¬μš©μžκ°€ 확인할 μ—λŸ¬λ©”μ„Έμ§€λŠ” μ•„λ‹ˆκ² μ§€λ§Œμš”)

Comment on lines +9 to +19
class SignUpViewModelFactory :ViewModelProvider.Factory {
override fun <T : ViewModel> create(modelClass: Class<T>): T {
if (modelClass.isAssignableFrom(SignUpViewModel::class.java)) {
val repository =
AuthRepoImpl(ServicePool.authService)//authServiceλ₯Ό 인자둜 λ°›μ•„μ„œ RepositoryμΈμŠ€ν„΄μŠ€ 생성
return SignUpViewModel(repository) as T
} else {
throw IllegalArgumentException("Failed to create ViewModel: ${modelClass.name}")
}
}
}
Copy link
Member

Choose a reason for hiding this comment

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

μ΄λŸ¬ν•œ ViewModelProvider.Factoryλ₯Ό μƒμ†λ°›λŠ” Factory듀은 각 λ·°λͺ¨λΈ λ³„λ‘œ λ§Œλ“€ ν•„μš”λŠ” μ—†μŠ΅λ‹ˆλ‹€!
ν•˜λ‚˜μ˜ ViewModel Classλ§Œμ„ λ§Œλ“€κ³ 
if else ν˜Ήμ€ when문을 톡해 각 λ·°λͺ¨λΈκ³Ό repository λ³„λ‘œ λΆ„κΈ°μ²˜λ¦¬ ν•˜λ©΄ λ©λ‹ˆλ‹€!

κ·Έλƒ₯ else ifλ¬Έ ν•˜λ‚˜ 더 μΆ”κ°€ν•΄μ„œ 같은 λ°©μ‹μœΌλ‘œ 각 λ·°λͺ¨λΈ ν”„λ‘œλ°”μ΄λ” λ³„λ‘œ λ˜‘κ°™μ΄ μ„ μ–Έν•΄ μ£Όλ©΄ λ©λ‹ˆλ‹€.

ν•œλ²ˆ 해보고 μ•ˆλ˜λ©΄ μ§ˆλ¬Έμ£Όμ„Έμš”

Copy link
Member

@OliviaYJH OliviaYJH left a comment

Choose a reason for hiding this comment

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

닫을 이슈 번호 μž‘μ„± μ•ˆν–ˆμ–΄μš”!
그리고 μ™„μ „ μ„±μž₯ν•˜μ…¨λ„€μš”!!πŸ‘πŸ‘
μ™„μ „ μˆ˜κ³ ν•˜μ…¨μŠ΅λ‹ˆλ‹Ή!

import com.sopt.now.domain.model.AuthData
import retrofit2.Response

class AuthRepoImpl(
Copy link
Member

Choose a reason for hiding this comment

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

였호 λ ˆν¬μ§€ν† λ¦¬ νŒ¨ν„΄ 이번 μ„Έλ―Έλ‚˜μ—μ„œ λ°°μ› λŠ”λ° 벌써 μ μš©ν•˜μ…¨κ΅°μš₯!! 저도 μ μš©ν•΄λ΄μ•Όκ² μ–΄μš”!

@@ -52,13 +53,14 @@ class LoginActivity : AppCompatActivity() {
})
}

private fun getLogInRequestDto(): RequestLogInDto {
private fun getLoginData(): AuthData {
val id = binding.etId.text.toString()
val password = binding.pw2.text.toString()
Copy link
Member

Choose a reason for hiding this comment

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

pw2λ₯Ό 쑰금 더 μ˜λ―ΈμžˆλŠ” 아이디λͺ…μœΌλ‘œ λ°”κΎΈλ©΄ 쒋을 것 κ°™μ•„μš”!

Comment on lines 22 to 26
val userId = response.headers()["Location"]
userId?.let {
[email protected] =it
loginResult.value = true
}
Copy link
Member

Choose a reason for hiding this comment

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

μ˜€ν™ μ΄κ±°λŠ” λͺ°λžλ˜ λ‚΄μš©μ΄μ—μš”! μƒˆλ‘­κ²Œ μ•Œμ•„κ°€μš”!

Copy link
Member

@cacaocoffee cacaocoffee left a comment

Choose a reason for hiding this comment

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

μˆ˜κ³ ν•˜μ…¨μ–΄μš”! μ—„μ²­ μ—΄μ‹¬νžˆ ν•˜λŠ”κ²Œ λŠκ»΄μ§€λ„€μš”.. νŒ©ν† λ¦¬μ— λ ˆν¬μ§€ν† λ¦¬ νŒ¨ν„΄κΉŒμ§€.. λ©‹μžˆμ–΄μš”!

Comment on lines 31 to 32


Copy link
Member

Choose a reason for hiding this comment

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

μ—¬κΈ° 쀄간격 ν•˜λ‚˜ μ€„μ—¬μ£Όμ‹œλ©΄ 쒋을거 κ°™μ•„μš”

Copy link
Member

Choose a reason for hiding this comment

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

λ ˆν¬μ§€ν† λ¦¬κΉŒμ§€ μ“°λ‹€λ‹ˆ.. 폼미쳀닀

Comment on lines 22 to 26
val userId = response.headers()["Location"]
userId?.let {
[email protected] =it
loginResult.value = true
}
Copy link
Member

Choose a reason for hiding this comment

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

저두 λͺ°λžλ˜ λ‚΄μš© μƒˆλ‘­κ²Œ μ•Œμ•„κ°€μš”!

Comment on lines +8 to +18
class LoginViewModelFactory : ViewModelProvider.Factory{
override fun <T : ViewModel> create(modelClass: Class<T>): T {
if (modelClass.isAssignableFrom(LoginViewModel::class.java)) { //modelClassκ°€ LoginViewModel인지 확인
val repository =
AuthRepoImpl(ServicePool.authService)//authServiceλ₯Ό 인자둜 λ°›μ•„μ„œ RepositoryμΈμŠ€ν„΄μŠ€ 생성
return LoginViewModel(repository) as T
} else {
throw IllegalArgumentException("Failed to create ViewModel: ${modelClass.name}")
}
}
}
Copy link
Member

Choose a reason for hiding this comment

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

λ·°λͺ¨λΈ νŽ™ν† λ¦¬κΉŒμ§€...γ„·γ„·

Comment on lines 62 to 66
return AuthData(
id = id,
pw = password,
name = nickname,
phone = phoneNumber
Copy link
Member

Choose a reason for hiding this comment

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

Suggested change
return AuthData(
id = id,
pw = password,
name = nickname,
phone = phoneNumber
return AuthData(
id = binding.etIdSignup.text.toString(),
pw = binding.etPwSignup.text.toString(),
name = binding.etNicknameSignup.text.toString(),
phone = binding.etMbtiSignup.text.toString()

μ΄λ ‡κ²Œ λΆˆν•„μš”ν•œ λ³€μˆ˜ 생성없이 μ‚¬μš©ν•˜λ©΄ μ½”λ“œ 쀄일 수 μžˆμ„κ±° κ°™μ•„μš”

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants