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

WEEK7 : 필수과제 완료 #5

Open
wants to merge 3 commits into
base: develop
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
3 changes: 3 additions & 0 deletions app/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -70,4 +70,7 @@ dependencies {
// define any required OkHttp artifacts without version
implementation("com.squareup.okhttp3:okhttp")
implementation("com.squareup.okhttp3:logging-interceptor")

// kotlinx 라이브러리
implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-android:1.3.9'
}
9 changes: 5 additions & 4 deletions app/src/main/java/org/sopt/dosopttemplate/AuthService.kt
Original file line number Diff line number Diff line change
Expand Up @@ -9,21 +9,22 @@ import org.sopt.dosopttemplate.data.ResponseMemberCheckDto
import org.sopt.dosopttemplate.data.ResponseMemberDto
import org.sopt.dosopttemplate.data.ResponseSignUpDto
import retrofit2.Call
import retrofit2.Response
import retrofit2.http.Body
import retrofit2.http.GET
import retrofit2.http.POST
import retrofit2.http.Query

interface AuthService {
@POST("api/v1/members")
fun signup(
suspend fun signup(
@Body request: RequestSignUpDto,
):Call<ResponseSignUpDto> // 응답이 왓을 때 Callback으로 불려질 타입
):Response<ResponseSignUpDto> // 응답이 왓을 때 Callback으로 불려질 타입

@POST("api/v1/members/sign-in")
fun login(
suspend fun login(
@Body request: RequestLoginDto,
): Call<ResponseLoginDto>
): Response<ResponseLoginDto>

@GET("api/v1/members/{memberId}")
fun memberInfo(
Expand Down
56 changes: 56 additions & 0 deletions app/src/main/java/org/sopt/dosopttemplate/AuthViewModel.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
package org.sopt.dosopttemplate

import android.provider.ContactsContract.CommonDataKinds.Nickname
import androidx.lifecycle.ViewModel
import androidx.lifecycle.viewModelScope
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.StateFlow
import kotlinx.coroutines.flow.asStateFlow
import kotlinx.coroutines.launch
import org.sopt.dosopttemplate.ServicePool.authService
import org.sopt.dosopttemplate.data.RequestLoginDto
import org.sopt.dosopttemplate.data.RequestSignUpDto

class AuthViewModel : ViewModel() {

// UI State 사용
private val _loginState = MutableStateFlow<LoginState>(LoginState.Loading)
val loginState: StateFlow<LoginState> = _loginState.asStateFlow()

private val _signUpState = MutableStateFlow<SignUpState>(SignUpState.Loading)
val signUpState: StateFlow<SignUpState> = _signUpState.asStateFlow()

fun login(id: String, password: String) {
viewModelScope.launch {
kotlin.runCatching {

Choose a reason for hiding this comment

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

Suggested change
kotlin.runCatching {
runCatching {

지워줘도 됩니둥

val response = authService.login(RequestLoginDto(id, password))
response.body()
}.onSuccess {
if(it != null){
_loginState.value = LoginState.Success(it)
} else{
_loginState.value = LoginState.Error
}
}.onFailure {
_loginState.value = LoginState.Error
}
}
}

fun signUp(id: String, password: String, nickname: String){
viewModelScope.launch {
kotlin.runCatching {
val response = authService.signup(RequestSignUpDto(id, password, nickname))
response.body()
}.onSuccess {
if(it!=null) {

Choose a reason for hiding this comment

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

코드 정렬을 생활화 합시다

_signUpState.value = SignUpState.Success(it)
}else{
_signUpState. value = SignUpState.Error

Choose a reason for hiding this comment

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

value 띄어쓰기 부분! 붙여야 할 것 같아요~

}
}.onFailure {
_signUpState.value = SignUpState.Error
}
}
}
}
43 changes: 33 additions & 10 deletions app/src/main/java/org/sopt/dosopttemplate/LoginActivity.kt
Original file line number Diff line number Diff line change
Expand Up @@ -2,26 +2,25 @@ package org.sopt.dosopttemplate

import android.content.Intent
import android.os.Bundle
import android.util.Log
import androidx.activity.viewModels
import androidx.appcompat.app.AppCompatActivity
import org.sopt.dosopttemplate.ServicePool.authService
import org.sopt.dosopttemplate.Utils.UserInfo
import androidx.lifecycle.lifecycleScope
import kotlinx.coroutines.flow.collect
import kotlinx.coroutines.launch
import org.sopt.dosopttemplate.Utils.showToast
import org.sopt.dosopttemplate.data.RequestLoginDto
import org.sopt.dosopttemplate.data.ResponseLoginDto
import org.sopt.dosopttemplate.databinding.ActivityLoginBinding
import retrofit2.Call
import retrofit2.Response

class LoginActivity : AppCompatActivity() {
private lateinit var binding: ActivityLoginBinding
private val authViewModel by viewModels<AuthViewModel>()

override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
binding = ActivityLoginBinding.inflate(layoutInflater)
setContentView(binding.root)

signup()
observeLoginResult()
login()
}

Expand All @@ -32,7 +31,12 @@ class LoginActivity : AppCompatActivity() {
val id = binding.etLoginIdIdHint.text.toString()
val pw = binding.etLoginIdPwHint.text.toString()

// Request 요청 : RequestLoginDto body 담아주기
authViewModel.login(
id = id,
password = pw
)

/*// Request 요청 : RequestLoginDto body 담아주기
authService.login(RequestLoginDto(id, pw))
// enqueue : 비동기 방식으로 네트워크 요청 보내고, 결과를 받아 알맞게 처리
// Callback 인터페이스를 구현한 객체를 전달
Expand Down Expand Up @@ -67,12 +71,31 @@ class LoginActivity : AppCompatActivity() {
showToast("네트워크 오류 발생")
}
}
)
)*/
}
}

private fun observeLoginResult() {
lifecycleScope.launch {
authViewModel.loginState.collect{ loginState ->
when(loginState){
is LoginState.Success -> {
showToast("로그인 성공")
startActivity(Intent(this@LoginActivity, HomeActivity::class.java))
}
is LoginState.Error -> {
showToast("로그인 실패")
}
is LoginState.Loading -> {
showToast("로그인 중")
}
}
}
}
}

// 회원가입 버튼 클릭 시
private fun signup(){
private fun signup() {
// 회원가입 페이지로 이동
binding.btnLoginIdSignUp.setOnClickListener {
// Intent 실행
Expand Down
9 changes: 9 additions & 0 deletions app/src/main/java/org/sopt/dosopttemplate/LoginState.kt

Choose a reason for hiding this comment

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

하나의 UIState를 만들어서 적용할 수도 있답니다! LoginState와 SignUpState를 따로 나누지 않고요

Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
package org.sopt.dosopttemplate

import org.sopt.dosopttemplate.data.ResponseLoginDto

sealed class LoginState{
object Loading : LoginState()
data class Success(val data: ResponseLoginDto) : LoginState()
object Error : LoginState()
}
59 changes: 29 additions & 30 deletions app/src/main/java/org/sopt/dosopttemplate/SignUpActivity.kt
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,13 @@ package org.sopt.dosopttemplate
import android.content.Intent
import android.os.Bundle
import android.util.Log
import androidx.activity.viewModels
import androidx.appcompat.app.AppCompatActivity
import androidx.lifecycle.lifecycleScope
import com.google.android.material.datepicker.MaterialDatePicker
import com.google.android.material.snackbar.Snackbar
import kotlinx.coroutines.flow.collect
import kotlinx.coroutines.launch
import org.sopt.dosopttemplate.ServicePool.authService
import org.sopt.dosopttemplate.Utils.showToast
import org.sopt.dosopttemplate.data.RequestSignUpDto
Expand All @@ -22,6 +26,7 @@ import kotlin.properties.Delegates
class SignUpActivity : AppCompatActivity() {
lateinit var binding: ActivitySignUpBinding
private var available by Delegates.notNull<Boolean>()
private val authViewModel by viewModels<AuthViewModel>()

override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
Expand All @@ -30,6 +35,7 @@ class SignUpActivity : AppCompatActivity() {

birth()
signup()
observeSignUpResult()
}

// 생일 정보 입력
Expand Down Expand Up @@ -116,39 +122,32 @@ class SignUpActivity : AppCompatActivity() {
if (available) {
showToast("중복된 아이디입니다.")
} else if (testResult && !available) { // 조건이 적절하고 중복된 아이디가 아닌 경우
authService.signup(RequestSignUpDto(id, pw, nickname))
.enqueue(object : retrofit2.Callback<ResponseSignUpDto> {
override fun onResponse(
call: Call<ResponseSignUpDto>,
response: Response<ResponseSignUpDto>
) {
when (response.code()) {
201 -> {
// 회원가입 성공
showToast("회원가입 성공!")
val intent =
Intent(this@SignUpActivity, LoginActivity::class.java)
startActivity(intent)
}

400 -> {
// 회원가입 실패
showToast("회원가입에 실패했습니다.")
}

else -> {
showToast("서버 에러 발생")
}
}
}

override fun onFailure(call: Call<ResponseSignUpDto>, t: Throwable) {
showToast("네트워크 에러 발생")
}
})
authViewModel.signUp(

Choose a reason for hiding this comment

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

authViewModel의 signup과 버튼을 누르는 signup함수 이름이 같아서 조금 헷갈렸어요.
구분해주면 더 좋을 것 같아요!

id = id,
password = pw,
nickname = nickname
)
} else {
showToast("올바른 정보를 입력해주세요.")
}
}
}

private fun observeSignUpResult(){
lifecycleScope.launch {
authViewModel.signUpState.collect{ SignUpState ->
when(SignUpState){
is SignUpState.Success -> {
showToast("회원가입 성공")
}
is SignUpState.Error -> {
showToast("회원가입 실패")
}
is SignUpState.Loading -> {
showToast("회원가입 중")
}
}
}
}
}
}
9 changes: 9 additions & 0 deletions app/src/main/java/org/sopt/dosopttemplate/SignUpState.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
package org.sopt.dosopttemplate

import org.sopt.dosopttemplate.data.ResponseSignUpDto

sealed class SignUpState {
object Loading : SignUpState()
data class Success(val data: ResponseSignUpDto) : SignUpState()
object Error : SignUpState()
}