>챌린지반 강의
1. Json(JavaScript Object Notation)
1)Client - REST API server간 통신
-예전엔 HTML코드로 통신
=>문제점: 웹브라우저는 이해되는데 안드로이드같은 곳에선 알아볼 수 없음
-지금은 Json으로 통신
=>웹브라우저뿐만이 아니라 다른 OS들도 데이터를 인식하기 쉬워짐
2)구조 : Key - Value 형태
-{ } 는 Object
-[ ] 는 Array
3)convert에 사용할 dataclass
-"reponse" : { } => val Reponse: Body //오브젝트는 해당 부분을 데이터 클래스로
@최상위에 { }로 시작하면 해당 오브젝트에 대응되는 data class를 만들어야 한다.
-"List" : [ ] => val List: List<~> // 리스트는 리스트 형태로
-type: nullable인지 nonNull 인지 알아야 한다.
2. 비동기 프로그래밍
1)배터리 절약: 실행시간을 줄이고 HTTP 연결을 줄이는것
=>비동기 프로그래밍을 하면 실행시간이 줄어들음
2)async
-val lists = listOf( async{foo1()}, async{ foo2()}, ...)
=>val data = lists.awaitAll()하면 한번에 처리 가능
-async 블록의 반환값: 마지막 라인으로 해도 되지만 return@async로 해도 됨
=>async{ return@async ~ }
>Compose강의
1. 사전 정리내용
-LaunchedEffect
1)구조: LaunchEffect(key) //한번만 실행시키고 싶으면 key에 Unit
2)작동방식: composable이 처음 구성될때 실행되며 key값이 변경될 때마다 다시 실행됨
=>Recomposition이 일어나도 key값이 그대로면 재실행되지 않음
3)특징: 내부에 코루틴을 사용할 수 있음
4)주요 사용 예시
-초기 데이터 가져오기: 화면 처음구성시 데이터 불러오거나 초기화
-비동기 작업: 네트워크 요청, 데이터베이스 호출=>근데 이건 뷰모델이나 도메인에서
=>왜냐하면 composable에선 UI작업을 해야하지 다른 작업을 하면 안됨.
-애니메이션 시작
@예시
var pulseRateMs by remember { mutableStateOf(3000L) }
val alpha = remember { Animatable(1f) }
LaunchedEffect(pulseRateMs) { // Restart the effect when the pulse rate changes
while (isActive) {
delay(pulseRateMs) // Pulse the alpha every pulseRateMs to alert the user
alpha.animateTo(0f)
alpha.animateTo(1f)
}
}
5)유의점: LaunchedEffect는 composable함수이므로 Composable함수 내에서만 사용 가능
-rememberCoroutineScope
1)사용:
-컴포저블 외부에 있으면서 컴포지션 종료후 자동으로 취소되도록 범위가 지정된 코루틴 실행
-코루틴의 수명주기를 수동으로 관리할시
=>사용자 이벤트 발생시 애니메이션 취소해야 하는 경우
2)특징:
-수명주기가 컴포저블의 라이프 사이클과 일치
=>컴포저블이 화면에서 제거되면 코루틴도 취소
-recomposition에 영향을 받지 않음: recomposition이 발생해도 스코프가 유지되어 중복실행이나 리소스낭비 방지
3)주요 사용
-사용자 상호작용처리: 버튼 클릭. 스크롤등 상호작용에 따른 비동기 작업 처리시
@예시
@Composable
fun MoviesScreen(snackbarHostState: SnackbarHostState) {
// Creates a CoroutineScope bound to the MoviesScreen's lifecycle
val scope = rememberCoroutineScope()
Scaffold(
snackbarHost = {
SnackbarHost(hostState = snackbarHostState)
}
) { contentPadding ->
Column(Modifier.padding(contentPadding)) {
Button(
onClick = {
// Create a new coroutine in the event handler to show a snackbar
scope.launch {
snackbarHostState.showSnackbar("Something happened!")
}
}
) {
Text("Press me")
}
}
}
}
-rememberUpdatedState
1)사용: 코루틴, 타이머, 리스터와 같은 비동기 작업이나 오래 실행되는 작업에서 Recomposition이 일어나더라도 최신 상태를 안전하게 참조하기 위해 사용하는 것
2)예시
-문제 발생 상황: 비동기 작업에서 이전 상태를 참조하는 경우
@Composable
fun Timer(onTimeout: () -> Unit, timeoutDuration: Long) {
LaunchedEffect(timeoutDuration) {
delay(timeoutDuration)
onTimeout() // 이 시점에서 onTimeout이 오래된 참조일 수 있음
}
Text("Waiting for $timeoutDuration milliseconds...")
}
=>onTimeout이 바뀌어 리컴포지션이 일어나더라도 LaunchedEffect는 키값의 변화가 아니면 영향을 받지 않으므로 나중에 실행할때 오래된 onTimeout객체를 참조하고 있는 문제가 발생
-해결
@Composable
fun Timer(onTimeout: () -> Unit, timeoutDuration: Long) {
// 최신 onTimeout 콜백 참조를 기억
val updatedOnTimeout by rememberUpdatedState(onTimeout)
LaunchedEffect(timeoutDuration) {
delay(timeoutDuration)
updatedOnTimeout() // 항상 최신의 onTimeout을 호출
}
Text("Waiting for $timeoutDuration milliseconds...")
}
=>rememberUpdatedState()을 사용하면 해당 값이 최신객체를 참조하고 있도록 해줌
-DisposableEffect: Composable의 lifecycle에 맞춰 리소스 정리가 필요할때 사용
1)구조:
DisposableEffect(key){
.
.
.
onDispose{ ~ }
}
2)작동:
-DisposableEffect블록: 처음 Composition시와 key값이 바뀔때마다 실행됨
-onDispose블록: key값이 바뀔때와 Composable종료(컴포저블이 화면에서 제거되거나 컴포지션 종료)시 실행됨
3)사용
-컴포지션 시작시 리소스 초기화하고 컴포지션 종료시 정리작업이 필요할때
-key값이 변경될때마다 기존 리소스를 정리하고 새 리소스 초기화가 필요할때
@여기서 리소스에는 리스너 같은것도 포함
4)예시
@Composable
fun MyComposable(lifecycleOwner: LifecycleOwner) {
// DisposableEffect를 사용하여 생명주기 관찰자 등록
DisposableEffect(lifecycleOwner) {
val observer = object : LifecycleObserver {
@OnLifecycleEvent(Lifecycle.Event.ON_RESUME)
fun onResume() {
println("ON_RESUME 이벤트 발생")
}
@OnLifecycleEvent(Lifecycle.Event.ON_PAUSE)
fun onPause() {
println("ON_PAUSE 이벤트 발생")
}
}
// 생명주기 관찰자 등록
lifecycleOwner.lifecycle.addObserver(observer)
// 컴포지션이 종료되거나 key가 변경될 때 호출되어 관찰자 해제
onDispose {
lifecycleOwner.lifecycle.removeObserver(observer)
println("관찰자 해제됨")
}
}
// UI 코드
Text("Lifecycle aware component")
}
2. 강의 정리
-단발성 이벤트 전달은 sharedFlow로 주로 함
-컴포서블의 라이프사이클오너 받는법: LocalLifecycleOwner.current
=>라이프 라이클의 특정 시점마다 받복 실행:
lifecycleOwner.lifecycle.repeatOnLifecycle(Lifecycle.State.~){
launch{ ~ }
}
=>코루틴 스코프내에서 사용가능
-컴포스에선 AlertDialog로 다이얼로그 띄움
-ActivityforResult은 rememberLauncherForActivityResult
-find{} 조건에 맞는게 있으면 원소를 찾고 아니면 null
'코틀린-안드로이드' 카테고리의 다른 글
팀프로젝트 (0) | 2024.08.23 |
---|---|
70일차)특강(flow, Uistate), 팀프로젝트(YoutubeProject) (1) | 2024.08.19 |
68일차)알고리즘 문제(퍼즐 조각 채우기), 특강(Room, 인터페이스로 데이터 동기화, adapter MVVM구조에서 유의점, 인터페이스를 이용한 데이터 동기화) (0) | 2024.08.09 |
67일차)알고리즘 문제(가장 먼 노드, 순위), 개인과제(이미지 검색앱 만들기) (0) | 2024.08.08 |
66일차)알고리즘 문제(여행경로, 입국심사), Compose수업(Recomposition, State, Hoisting), Hilt Scope랑 InstallIn사용시 유의점 (0) | 2024.08.07 |