>챌린지반 강의
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
'코틀린-안드로이드' 카테고리의 다른 글
| 팀프로젝트 (1) | 2024.08.23 | 
|---|---|
| 70일차)특강(flow, Uistate), 팀프로젝트(YoutubeProject) (3) | 2024.08.19 | 
| 68일차)알고리즘 문제(퍼즐 조각 채우기), 특강(Room, 인터페이스로 데이터 동기화, adapter MVVM구조에서 유의점, 인터페이스를 이용한 데이터 동기화) (0) | 2024.08.09 | 
| 67일차)알고리즘 문제(가장 먼 노드, 순위), 개인과제(이미지 검색앱 만들기) (1) | 2024.08.08 | 
| 66일차)알고리즘 문제(여행경로, 입국심사), Compose수업(Recomposition, State, Hoisting), Hilt Scope랑 InstallIn사용시 유의점 (0) | 2024.08.07 |