티스토리 뷰
2023년 07월 4주 차 일기입니다.
이번 주에는 우선 코드랩 학습을 진행하였습니다.
https://developer.android.com/codelabs/jetpack-compose-advanced-state-side-effects?hl=ko#0
사용해보지 않았던 내용이 많아서 추후에 상황에 따라 사용해 봐야겠습니다.
코드랩 학습을 진행하면서 컴포저블을 만들 때 공통부분과 약간 수정한 버전?을 따로 만들어서 관리하는 게 잘 되어있다고 느꼈습니다.
그래서 저도 조금 더 상세하게 컴포저블을 만들어서 관리해야겠다고 생각하였습니다.
다음은 진행하던 프로젝트의 구조를 변경하였습니다.
어떻게 하면 좋을까 많이 고민하였습니다.
나중에 수정할 수도 있겠지만 일단은 방향은 정했습니다.
개발을 진행하는 도중 로딩 화면과 네트워크 오류 화면을 앱에 넣고 싶다는 생각이 들었습니다. 당연히 화면 단위로 각자 구현하는 건 실수로 빼먹을 가능성과 관리하기 힘들다는 문제가 있으니 공용으로 사용할 무언가가 필요했습니다.
고민을 하던 중 코드랩을 통해 collectAsStateWithLifecycle()를 알게 되었습니다.
이걸 이용해서 화면의 상태를 관리해 보려고 합니다.
class BaseStatus {
var message by mutableStateOf("")
private set
var isLoading by mutableStateOf(false)
private set
var isNetworkError by mutableStateOf(false)
private set
fun updateMessage(message: String) {
this.message = message
}
fun startLoading() {
isLoading = true
isNetworkError = false
}
fun endLoading() {
isLoading = false
}
fun updateNetworkErrorState(value: Boolean) {
isNetworkError = value
}
}
상태를 관리하기 위한 클래스입니다.
나중에 더 추가할지는 모르겠지만 우선 메시지와 로딩 여부, 네트워크 여부를 저장하고 있습니다.
또한 private set을 이용해서 BaseStatus의 함수를 이용해서만 값을 변경하게 하였습니다.
abstract class BaseViewModel: ViewModel() {
private val _status = MutableStateFlow(BaseStatus())
val status: StateFlow<BaseStatus> = _status
protected fun startLoading() {
_status.value.startLoading()
}
protected fun endLoading() {
_status.value.endLoading()
}
protected fun updateMessage(message: String) {
_status.value.updateMessage(message)
}
protected fun updateNetworkErrorState(value: Boolean) {
_status.value.updateNetworkErrorState(value)
}
}
공용으로 사용할 ViewModel입니다.
StateFlow 변수와 값을 변경할 함수들입니다.
상황에 맞게 함수를 이용하여 상태 값을 관리합니다.
@Composable
fun BaseStructureScreen(
status: BaseStatus,
errorScreen: @Composable () -> Unit,
content: @Composable () -> Unit,
) {
val context = LocalContext.current
Box(
modifier = Modifier
.fillMaxSize()
.background(MyColorWhite)
) {
if (status.isNetworkError) {
errorScreen()
} else {
content()
}
if (status.isLoading) {
LoadingScreen()
}
}
LaunchedEffect(status.message) {
if (status.message.trim().isEmpty()) return@LaunchedEffect
context.toast(status.message)
}
}
기본 구조의 컴포저블을 위와 같이 만들어 보았습니다.
네트워크 에러가 발생할 시에는 errorScreen을 아니면 content를 표시합니다.
또한 로딩 중일 때에는 LoadingScreen을 표시합니다.
message의 값이 변경되면 내용을 ToastMesaage로 출력합니다.
@Composable
fun BaseContainer(
status: BaseStatus,
paddingValues: PaddingValues = PaddingValues(top = 22.dp, start = 20.dp, end = 17.dp),
reload: (() -> Unit)? = null,
onBackClick: (() -> Unit)? = null,
color: Color = MyColorRed,
errorScreen: (@Composable () -> Unit)? = null,
content: @Composable ColumnScope.() -> Unit
) {
BaseStructureScreen(
status = status,
content = {
Column(
modifier = Modifier
.fillMaxSize()
.padding(paddingValues)
) {
content()
}
},
errorScreen = {
if (errorScreen != null)
errorScreen()
else {
NetworkErrorScreen(
onBackClick = onBackClick,
color = color,
reload = {
reload?.invoke()
}
)
}
}
)
}
그다음 BaseStructureScreen을 좀 더 수월하게 사용할 수 있게 만들어 주었습니다.
마지막으로 가장 많은 형태로 사용될 형태 2가지를 만들어 주었습니다.
@Composable
fun HeaderBodyContainer(
status: BaseStatus,
paddingValues: PaddingValues =
PaddingValues(top = 22.dp, start = 20.dp, end = 17.dp, bottom = 10.dp),
reload: (() -> Unit)? = null,
onBackClick: (() -> Unit)? = null,
color: Color = MyColorRed,
errorScreen: (@Composable () -> Unit)? = null,
headerContent: @Composable () -> Unit,
bodyContent: @Composable () -> Unit
) {
BaseContainer(
status = status,
paddingValues = paddingValues,
reload = reload,
onBackClick = onBackClick,
color = color,
errorScreen = errorScreen
) {
headerContent()
Box(modifier = Modifier.weight(1f)) {
bodyContent()
}
}
}
@Composable
fun HighMediumLowContainer(
status: BaseStatus,
paddingValues: PaddingValues =
PaddingValues(top = 22.dp, start = 20.dp, end = 17.dp, bottom = 10.dp),
reload: (() -> Unit)? = null,
onBackClick: (() -> Unit)? = null,
color: Color = MyColorRed,
errorScreen: (@Composable () -> Unit)? = null,
heightContent: @Composable () -> Unit,
mediumContent: @Composable () -> Unit,
lowContent: @Composable () -> Unit
) {
BaseContainer(
status = status,
paddingValues = paddingValues,
reload = reload,
onBackClick = onBackClick,
color = color,
errorScreen = errorScreen
) {
heightContent()
Box(modifier = Modifier.weight(1f)) {
mediumContent()
}
lowContent()
}
}
이렇게 구조를 결정을 하고 이를 바탕으로 기존에 만들어 두었던 화면들을 수정하는 작업을 진행하였습니다.
아직 다는 못 해서 다음 주에도 마저 작업을 진행하고 새로운 화면의 작업을 할 예정입니다.
'안드로이드 > 일기' 카테고리의 다른 글
2023.08.07 ~ 08.13 (0) | 2023.08.13 |
---|---|
2023.07.31 ~ 08.06 일기 (0) | 2023.08.07 |
2023년 7월 일기 (0) | 2023.07.23 |
2023년 6월 3 ~ 4주 차 일기 (0) | 2023.06.25 |
2023년 6월 1 ~ 2주 차 일기 (0) | 2023.06.11 |
- Total
- Today
- Yesterday
- Kotlin
- WebView
- Fast api
- compose
- WorkManager
- Compose BottomSheetScaffold
- column
- Compose 네이버 지도
- Compose QRCode Scanner
- Compose BottomSheetDialog
- Android Compose
- Gradient
- 안드로이드
- Compose 네이버 지도 api
- Worker
- 안드로이드 구글 지도
- Compose BottomSheet
- Duplicate class found error
- Duplicate class fond 에러
- Retrofit
- Compose ConstraintLayout
- Android
- Row
- Compose ModalBottomSheetLayout
- 웹뷰
- Pokedex
- 포켓몬 도감
- Compose MotionLayout
- Compose Naver Map
- LazyColumn
일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | 4 | 5 | 6 | 7 |
8 | 9 | 10 | 11 | 12 | 13 | 14 |
15 | 16 | 17 | 18 | 19 | 20 | 21 |
22 | 23 | 24 | 25 | 26 | 27 | 28 |
29 | 30 | 31 |