LiveData 파헤치기~~

woniwon·2024년 4월 1일
0

Android

목록 보기
17/19
post-thumbnail

Intro

다이어리 앱 만들기를 하면서 가장 어려웠던게 뭐에요? 라고 물어보면 진짜 무조건 "UI 상태 관리요;;" 라고 할 것이다. 스프링만 했던 나에게 상태관리란 참 낯선 존재.. 그리고 뭐 어케 작동하는지 알 수 있어야지😅
그래서 시간이 남은 김에 한번 UI 상태관리와 관련해서 공식문서를 찾아보고 정리를 해보려고 한다. 처음은 바로 Live Data..!!
한번 공부해보겠습미다.. 레쮸꼬~~🫣

모든 글은 노션에 개인적으로 공부한 글을 다시 업로드 하는거라 이상할 수 있습니다!! 그냥 코틀린 공부하는 입문자가 혼자 쓰는 블로그구나 생각해주세요!! 오류 사항이나 수정 사항은 알려주시면 저에게 큰 도움이 됩니다🌈


LiveData

  • 관찰 가능한 데이터 홀더 클래스로 수명 주기를 인식
  • UI 컴포넌트(예: 액티비티, 프래그먼트)가 데이터의 변경을 관찰하고, 데이터가 변경될 때마다 UI를 자동으로 업데이트할 수 있게 된다.
  • 데이터의 변경을 관찰하는 Observer들에게 알림을 보냄으로써 동작한다.

사용 이점

  • UI와 데이터 일치를 보장
  • 메모리 누수 없음 : ObserverLifecycle에 결합되어 있으며 연결된 수명 주기가 끝나면 자동 삭제됨
  • 중지된 활동으로 인한 비정상 종료 없음 : 관찰자의 수명 주기가 비활성 상태 (Started, Resumed제외)면 관찰자는 어떤 liveData 이벤트도 받지 않는다.
  • 수명주기 수동 처리 X
  • 최신 데이터 유지
  • 적절한 구성 변경 : 기기회전 같은 구성 변경으로 인해 acitivityfragment가 다시 생성되면 사용 가능한 최신 데이터를 즉시 다시 받음
  • 리소스 공유 : 앱에서 시스템 서비스를 공유할 수 있도록 싱글톤 패턴을 사용하는 [LiveData](https://developer.android.com/reference/androidx/lifecycle/LiveData?hl=ko) 객체를 확장하여 시스템 서비스를 래핑할 수 있다. LiveData 객체가 시스템 서비스에 한 번 연결되면 리소스가 필요한 모든 관찰자가 LiveData 객체를 볼 수 있다. 자세한 내용은 LiveData 확장을 참고

LiveData 객체 사용

  1. LiveData 인스턴스 생성 → viewModel 클래스 내

    class UserViewModel : ViewModel() {
        // LiveData 초기화 - 읽기 전용 데이터
        val userName: LiveData<String> = MutableLiveData("John Doe")
        
        // MutableLiveData 초기화 - 값 변경 가능
        private val _userName2 = MutableLiveData("John Doe")
        val userName2: LiveData<String> = _userName2
    
        // userName 값을 업데이트하는 함수
        fun updateUserName(newName: String) {
            _userName2.value = newName
        }
    • lazy : 실제로 getCurrentName이 사용되는 시점까지 객체 생성을 지연시켜 초기 리소스 소모를 최소화 한다.
      • 초기화 순서를 관리할 때, 다른 프로퍼티나 초기화 로직이 먼저 수행된 후에 필요한 경우도 유용
      • 스레드 안전 : lazy는 스레드 안전하며, 여러 스레드에서 동시에 접근해도 첫 번째로 접근한 스레드에 의해 한 번만 초기화되고, 이후 동일한 인스턴스 반환 → 멀티스레드 환경에서 안전하게 사용 가능
    • MutableLiveData<String>()의 인스턴스가 생성되고, 그 이후로는 같은 인스턴스를 재사용
  2. Observer 객체 생성 - onChanged()메서드를 정의 : LiveData가 보유한 데이터 변경시 발생하는 작업 제어 → Activity, Fragment 내

  3. Observe() 메서드를 활용해 LiveData에 Observer 객체 연결

    observe() 메서드는 LifeCycleOwner 객체를 활용함

    • 이때 observeForever(observer)를 활용하면 항상 수정에 관한 알림을 받을 수 있고, removeObserver(observer)를 사용하면 이런 관찰자를 삭제 할 수 있음

LiveData를 관찰할 때 쓰는 방법

1. observe(LifecycleOwner, Observer)

  • 특징 및 기능: 가장 기본적인 관찰 방법으로, LiveData에 변경 사항이 있을 때마다 실행될 코드 블록(Observer)을 정의한다. LifecycleOwner (예: 액티비티나 프래그먼트)는 관찰자가 관찰을 시작하고 중단해야 하는 시점을 결정하는 데 사용된다. 이 메서드를 사용하면 LiveData의 변경 사항을 안전하게 관찰하고, LifecycleOwner의 생명주기에 따라 자동으로 관찰을 중지하여 메모리 누수를 방지할 수 있다.

2. observeForever(Observer)

  • 특징 및 기능: LifecycleOwner 없이 LiveData를 관찰할 때 사용한다. 이 방법은 LiveData의 변경 사항을 생명주기와 무관하게 계속해서 관찰하고 싶을 때 유용하다. 그러나 observeForever로 등록된 관찰자는 수동으로 제거(removeObserver)해야 하며, 그렇지 않으면 메모리 누수가 발생할 위험이 있다!

3. observeAsState() (Jetpack Compose용)

  • 특징 및 기능: Jetpack Compose와 함께 사용되는 확장 함수로, LiveData를 Compose의 State 객체로 변환한다. 이를 통해 Composable 함수 내에서 LiveData의 최신 값을 쉽게 읽을 수 있으며, LiveData의 데이터가 변경될 때 자동으로 UI를 재구성(리컴포지션)한다.
  • 내가 가장 많이 사용!
    val selectedDate by viewModel.selectedDate.observeAsState(LocalDateTime.now())
    • 여기서 함수 내부는 초깃값으로 initial 매개변수를 통해 설정 가능!
    • 컴포즈와 함께 쓸 때 주의점! 고려할점
      • 컴포지션 재구성 최적화: LiveData 값이 변경될 때마다 관련된 Composable 함수가 재구성된다. 이는 때때로 불필요한 UI 업데이트를 초래할 수 있으므로, rememberderivedStateOf 같은 Compose 유틸리티를 사용하여 재구성을 최적화할 수 있다.
      • 비동기 작업과의 통합: LiveData를 사용하여 비동기 작업의 결과를 표시하는 경우, 상태 관리를 위해 로딩, 성공, 실패 상태를 나타내는 별도의 LiveData를 고려해야 할 수도 있다. 이러한 패턴은 사용자 인터페이스가 현재 상태를 보다 정확하게 반영할 수 있도록 도와준다.

4. hasActiveObservers()

  • 특징 및 기능: LiveData 객체에 활성 상태의 관찰자(Observer)가 있는지 여부를 확인LiveData가 관찰자에 의해 관찰되고 있는지 여부를 알고 싶을 때 유용하며, 주로 디버깅이나 특정 로직의 조건으로 사용될 수 있다
profile
단순 기록용 Velog 입니다.

0개의 댓글