-
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
[Feature/week_1_compose]: 1주차 과제 Compose 구성 #8
base: develop_compose
Are you sure you want to change the base?
Conversation
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.
의진님 미치신건가요 ? 너무 잘하네요 컴포즈까지 바쁜대 고생했숩니다.
코리달고 싶지만 컴포즈는 나약해서 ㅠㅠ mvi만 보이네요
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.
잘 보고 갑니다~ 저도 컴포즈 공부하면 꼭 다시 와야겠네요 고생하셨어요 ㅎㅎ
val nickname: String = "", | ||
) | ||
|
||
sealed interface MainSideEffect { |
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.
SideEffect는 보통 악영향, 예상치 못한 문제 이런곳에 사용하는 네이밍 아닌가요? 인터페이스 이름을 MainSideEffect로 하신 이유를 알고 싶습니다!
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.
의학용어에서는 그렇게 사용하긴 하지만 CS에서 사이드 이펙트라는 것은 어떤 행위에 대한 부수 효과(의도치 않는 생산물?) 정도로 받아들이면 좋을 것 같네요. 함수형 프로그래밍에서 자주 다뤄지는 개념입니다 (순수함수와 사이드 이펙트라는 용어로 말이죠)
) | ||
|
||
@Composable | ||
fun DoEuijinKwakTheme( |
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.
폼미쳤다
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.
고생했음
enum class Screen { | ||
LOGIN, | ||
SIGNUP, | ||
Home, |
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.
Home, | |
HOME; |
private val viewModel by viewModels<MainViewModel>() | ||
|
||
class MainActivity : AppCompatActivity() { | ||
override fun onCreate(savedInstanceState: Bundle?) { | ||
super.onCreate(savedInstanceState) | ||
setContentView(R.layout.activity_main) | ||
setContent { | ||
DoEuijinKwakTheme { | ||
val navController = rememberNavController() |
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.
private val viewModel by viewModels<MainViewModel>() | |
class MainActivity : AppCompatActivity() { | |
override fun onCreate(savedInstanceState: Bundle?) { | |
super.onCreate(savedInstanceState) | |
setContentView(R.layout.activity_main) | |
setContent { | |
DoEuijinKwakTheme { | |
val navController = rememberNavController() | |
override fun onCreate(savedInstanceState: Bundle?) { | |
super.onCreate(savedInstanceState) | |
setContent { | |
DoEuijinKwakTheme { | |
val navController = rememberNavController() | |
val viewModel: MainViewModel = viewModel() |
컴포즈에서는 delegate 방식이 아닌 함수 내에서 변수 선언방식으로 뷰모델을 불러올 수도 있습니다.
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.
오호 처음알았네요 그러면 저 viewmodel은 어떤 생명주기를 가지고있나요??
navController = navController, | ||
viewModel = viewModel, | ||
) | ||
} | ||
composable(Screen.SIGNUP.name) { | ||
SignUpScreen( | ||
navController = | ||
navController, | ||
viewModel = viewModel, | ||
) | ||
} | ||
composable(Screen.Home.name) { | ||
HomeScreen( | ||
navController = navController, | ||
viewModel = viewModel, |
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.
여러개의 화면에서 하나의 ViewModel을 공유하면 한 화면의 상태를 다른화면도 알 수 있는 상황도 있을 것 같네요. 괜찮긴 하지만 굳이 이걸 다 알아야하나라는 생각도 있습니다.
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.
맞습니다... 근데 보통 Auth관련 로직은 AppViewModel에 넣고 처리하는게 일반적인 방법이라고 생각되어 위처럼 구성해보았습니다
when (it) { | ||
is MainContract.MainSideEffect.ShowToast -> { | ||
Toast.makeText(this, it.message, Toast.LENGTH_SHORT).show() | ||
} | ||
|
||
is MainContract.MainSideEffect.LoginSuccess -> { | ||
Toast.makeText(this, "로그인 성공!", Toast.LENGTH_SHORT).show() | ||
navController.navigate(Screen.Home.name) | ||
} | ||
|
||
is MainContract.MainSideEffect.RegistrationSuccess -> { | ||
Toast.makeText(this, "회원가입 성공!", Toast.LENGTH_SHORT).show() | ||
navController.popBackStack() // 로그인 화면으로 돌아갑니다. | ||
} | ||
} | ||
}.launchIn(lifecycleScope) |
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.
이 방식은 주로 View에서 많이 사용하는 방식이고 Compose에서는 상태를 구독받을 때
val state by viewModel.state.collectStateWithLifecycle()
로 구독을 많이 받습니다. (그리고 이벤트도 거의 안쓰이고 대부분 UiState 선에서 다 해결할 수 있습니다.)
참고로 지난 DroidKaigi 샘플앱에서도 SharedFlow를 사용한 코드는 없었네요.
val nickname: String = "", | ||
) | ||
|
||
sealed interface MainSideEffect { |
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.
의학용어에서는 그렇게 사용하긴 하지만 CS에서 사이드 이펙트라는 것은 어떤 행위에 대한 부수 효과(의도치 않는 생산물?) 정도로 받아들이면 좋을 것 같네요. 함수형 프로그래밍에서 자주 다뤄지는 개념입니다 (순수함수와 사이드 이펙트라는 용어로 말이죠)
) | ||
Spacer(modifier = Modifier.size(8.dp)) | ||
Text( | ||
text = state.value.nickname, |
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.
text = state.value.nickname, | |
text = state.nickname, |
collect를 할 때 by 문법을 활용하면 바로 value에 접근할 수 있습니다.
) | ||
Spacer(modifier = Modifier.size(64.dp)) | ||
Text(text = "ID") | ||
TextField( |
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.
지금은 TextField를 사용해도 좋지만, TextField 구현체를 살펴보면 내부 modifier에서 이미 padding을 잡고 있어가지고 실제 현업에서는 BasicTextField를 커스텀해서 구현하곤 합니다...
viewModel.updateState( | ||
state.value.copy(registerId = textValue), | ||
) |
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.
state의 value를 View 단에서 변경시키고 있는 로직이라고 보여지는데 직접 MutableStateFlow의 value를 건드는 것도 아니어서 나중에 state 변경을 추적할 때 이 부분에서 버그가 발생하면 에러 추적이 더 어려워질 수도 있을 것 같네요.
함수 이름을 보면 그래도 어느정도 추론을 할 수는 있는 것 같아 그건 괜찮은데, 어떤 프로퍼티가 변경이 되었는지 일일히 다 찾아봐야하는 수고로움이 있을 것 같아서 Ui 내 State가 조금이라도 많아진다면 고생을 할 수도 있을 것 같습니다.
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.
오 이럴때는 보통 어떻게 처리하나요?
visualTransformation = PasswordVisualTransformation(), | ||
keyboardOptions = KeyboardOptions(keyboardType = KeyboardType.Password), | ||
) | ||
Spacer(modifier = Modifier.weight(1f)) |
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.
위의 부분과 아래부분을 Column으로 묶고 상위 Column의 verticalArrangement를 SpaceBetween으로 두면 됩니다.
fun LoginScreenPreview() { | ||
LoginScreen( | ||
navController = NavController(LocalContext.current), | ||
viewModel = MainViewModel(), |
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.
프리뷰 보여지나요? 이렇게 하면 안보여질텐데요.
추가 사항
스크린 샷
KakaoTalk_Video_2023-10-30-21-07-12.mp4