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

1주차 과제 #3

Merged
merged 27 commits into from
Oct 21, 2023
Merged

1주차 과제 #3

merged 27 commits into from
Oct 21, 2023

Conversation

Sangwook123
Copy link
Member

@Sangwook123 Sangwook123 commented Oct 10, 2023

📌𝘐𝘴𝘴𝘶𝘦𝘴

📎𝘞𝘰𝘳𝘬 𝘋𝘦𝘴𝘤𝘳𝘪𝘱𝘵𝘪𝘰𝘯

  • 액티비티 생명주기 알아보기
  • edittext 줄 제한
  • windowSoftInputMode
  • 키보드 숨기기
  • 자동로그인 구현
  • Intent 알아보기
  • 뒤로 두번눌러 종료

📷𝘚𝘤𝘳𝘦𝘦𝘯𝘴𝘩𝘰𝘵

4d67fb54-9a1f-4e14-99a0-5dbec100365c.mp4

💬𝘛𝘰 𝘙𝘦𝘷𝘪𝘦𝘸𝘦𝘳𝘴

로그아웃 이외에도 회원탈퇴기능도 추가적으로 넣어봤습니다.

추가로 MVVM, DI 등등 적용해봤슴니다

Copy link
Member

@Marchbreeze Marchbreeze left a comment

Choose a reason for hiding this comment

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

진짜 이남자... 탐난다

abstract fun bindsSharedPrefRepository(
sharedPrefRepository: SharedPrefRepositoryImpl
): SharedPrefRepository
}
Copy link
Member

Choose a reason for hiding this comment

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

@provides 대신 @BINDS 를 활용하신 이유가 있나요?

Copy link
Member Author

Choose a reason for hiding this comment

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

viewmodel에서 domain 레이어의 repository를 data의 구현부와 연결하여 사용하기위해 @BINDS 어노테이션을 활용했습니다

viewModel.setAutoLogin(user)
intent.flags = Intent.FLAG_ACTIVITY_NEW_TASK or Intent.FLAG_ACTIVITY_CLEAR_TASK
startActivity(intent)
}
Copy link
Member

Choose a reason for hiding this comment

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

intent에 .apply{} 로 한번에 연결된 코드를 만들면 더 깔끔한 코드가 될 것 같습니다 !

Suggested change
}
this.toast(getString(R.string.login_success_login))
viewModel.setAutoLogin(user)
Intent(this, MainActivity::class.java).apply{
putExtra(USER_KEY, user)
addFlags(FLAG_ACTIVITY_NEW_TASK or FLAG_ACTIVITY_CLEAR_TASK)
startActivity(this)
}

when (if (user == null) isValidLogin() else isValidLogin(user)) {
true -> _loginState.value = UiState.Success(sharedPrefRepository.getUserInfo())
false -> _loginState.value = UiState.Failure(CODE_FAILURE)
}
Copy link
Member

Choose a reason for hiding this comment

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

오호 when 문이 신기하네요 이거

} else {//미만일때
finish()
}
}
Copy link
Member

Choose a reason for hiding this comment

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

backPressedTime 처럼 1500도 따로 상수화해주시면 더 유지보수가 용이할 듯 합니다 ~~

_signupState.value = UiState.Failure(CODE_INVALID_NICKNAME)
} else {
_signupState.value = UiState.Failure(CODE_INVALID_HOBBY)
}
Copy link
Member

Choose a reason for hiding this comment

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

else if 말고 when 문으로 더 깔끔하게 case를 나눌 수 있을 것 같습니다 ~~

private const val MIN_ID_LENGTH = 6
private const val MAX_ID_LENGTH = 10
private const val MIN_PW_LENGTH = 8
private const val MAX_PW_LENGTH = 12
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

@kez-lab kez-lab left a comment

Choose a reason for hiding this comment

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

심화 도전 폼 무쳤고 가보자잇 ⚽️

app/build.gradle Outdated
Comment on lines 47 to 56
implementation 'androidx.constraintlayout:constraintlayout:2.1.4'
implementation 'com.google.code.gson:gson:2.10.1'
testImplementation 'junit:junit:4.13.2'
androidTestImplementation 'androidx.test.ext:junit:1.1.5'
androidTestImplementation 'androidx.test.espresso:espresso-core:3.5.1'
implementation "com.google.dagger:hilt-android:2.44"
kapt "com.google.dagger:hilt-compiler:2.44"
implementation 'androidx.activity:activity-ktx:1.2.2'
implementation 'androidx.fragment:fragment-ktx:1.3.3'
}
Copy link
Member

Choose a reason for hiding this comment

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

Gson도 좋지만 Kotlin serialization 이라는 라이브러리도 있습니다!

관련 글은 인간 안드로이드님의 블로그를 가져와봤어요 참고해보시면 좋을 것 같습니다!

Copy link
Member Author

Choose a reason for hiding this comment

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

넵 반영해보겠습니다 ㅎㅎ

Comment on lines 6 to 12
@Parcelize
data class User(
val id: String = "",
val pw: String = "",
val nickname: String = "",
val hobby: String = ""
) : Parcelable
Copy link
Member

Choose a reason for hiding this comment

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

Parcelable은 Android 플랫폼에 특화된 기능입니다, 따라서 Data Layer가 Android 프레임워크에 의존된 형태로 보입니다!

하지만 Data Layer에서는 데이터 액세스와 관련된 로직을 처리하기 때문에 Android 특정 의존성과 결합된다면 테스트의 용이성 및 유지보수 차원에서 문제가 발생할 수 있습니다.

그렇기 때문에 Presentation Layer의 Model을 통해서 Parcelize를 구현하는 것을 통해 의존성을 분리하는 것을 추천드립니다!

Comment on lines 1 to 12
package org.sopt.dosopttemplate.domain.repository

import org.sopt.dosopttemplate.data.entity.User

interface SharedPrefRepository {
fun saveUserInfo(user: User?)
fun getUserInfo(): User?
fun setAutoLogin()
fun isAutoLogin(): Boolean
fun clearAutoLogin()
fun clearSharedPref()
}
Copy link
Member

Choose a reason for hiding this comment

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

domain layer이기 때문에 domain 의존성만을 갖고있어야 할 것 같습니다! domain 패키지의 User Model 을 생성 후 Data Layer 의 User를 mapping하는 것을 추천드립니다!

Comment on lines +22 to +24
init {
autoLogin()
}
Copy link
Member

Choose a reason for hiding this comment

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

init Block 활용 너무 좋아욥~!!

@Sangwook123 Sangwook123 requested a review from leeeha October 13, 2023 10:58
Copy link

@amourxyoung amourxyoung left a comment

Choose a reason for hiding this comment

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

진짜 손폼미쳤네요... 너무너무 좋은 코드들이 많아서 많이 배워갑니당

val nickname: String? = "",
val hobby: String? = ""
) {
fun toUser(): User? {

Choose a reason for hiding this comment

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

엔티티화까지,,, 저두 이런식으로 리팩토링해야겠네요


import org.sopt.dosopttemplate.domain.entity.User

interface SharedPrefRepository {

Choose a reason for hiding this comment

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

진짜 mvvm 적용 폼 미쳤네,,,

private fun initLogoutStateObserver() {
viewModel.logoutState.observe(this) { state ->
when (state) {
is UiState.Success -> {

Choose a reason for hiding this comment

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

UiState 활용 굿이네용 👍

import android.os.Build.VERSION_CODES.TIRAMISU
import android.os.Parcelable

fun <T : Parcelable> Intent.getParcelable(key: String, c: Class<T>): T? = when {

Choose a reason for hiding this comment

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

이거 쇽샥해가겠습니다

@@ -0,0 +1,21 @@
package org.sopt.dosopttemplate.presentation.model

Choose a reason for hiding this comment

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

이건 presentation에서 데이터 클래스 생성해주신 이유가 따로 있으실까요?

Copy link
Member Author

Choose a reason for hiding this comment

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

클린 아키텍처를 적용하고자 했습니다 ! parcelable data class가 data layer에서 정의 내려진다면 의진님 말씀처럼 data layer가 안드로이드 프레임워크에 의존성을 갖게된다 생각했고 domain layer는 어느곳에도 의존성을 갖지 않도록 순수 코틀린 코드로만 작성하고자 했습니다. 그래서 presentation의 model에서 구현해 주었습니다.

@Sangwook123 Sangwook123 merged commit 77acd66 into develop Oct 21, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
심화 2️⃣ 심화 과제 도전 3️⃣ 도전 과제
Projects
None yet
Development

Successfully merging this pull request may close these issues.

1주차 과제
4 participants