[Android] LiveData

Minji Jeong·2022년 6월 9일
1

Android

목록 보기
19/37
post-thumbnail
LiveData에 대해 소개하기 전에 한가지 예시를 들어보겠다. 인스타그램 또는 트위터와 같은 SNS를 사용하는 회원들은 각자의 홈피를 가지고 있고, 다른 회원들의 홈피를 구경하며 맘에드는 게시물에 '좋아요'를 클릭한다. 좋아요를 클릭하면 버튼 바로 옆 텍스트에 하트를 클릭한 회원들의 수가 실시간으로 표시되는 것을 볼 수 있다. 혹시 로컬 데이터베이스나 서버로부터 데이터를 가져와 화면에 출력할 때, 값이 변경되도 화면에 업데이트가 되지 않아서 해결하기 위해 노력했던 경험이 있지 않은가? 우리는 이런 상황을 해결하기 위해 LiveData를 사용한다.

LiveData

LiveData는 Jetpack 라이브러리 중 하나로, 액티비티, 프래그먼트, 서비스 등 다른 앱 컴포넌트의 생명 주기를 고려하는 추상 클래스다. 보통 ViewModel과 연계해서 사용하며(View가 ViewModel이 가지고 있는 LiveData를 observe하는 형태로 사용), 각 컴포넌트의 생명 주기를 알고 있기 때문에 화면이 활성화될 경우에만 동작하여 화면을 늘 최신 상태로 업데이트 할 뿐만 아니라 메모리 누수도 예방할 수 있다는 장점이 있다.

pros and cons

LiveData는 앞서 언급했다 싶이 액티비티, 프래그먼트, 서비스와 같은 컴포넌트의 생명 주기를 알고 있기 때문에 생명 주기를 신경쓸 필요 없이 최신 UI 상태를 유지할 수 있다. 해당 컴포넌트가 비활성화 되었다가 다시 활성화될 때 알아서 최신 데이터를 받아오는 것은 물론, 화면이 활성화될 경우에만 동작하기 때문에 메모리 누수를 예방할 수 있다는 장점도 있다. 또한 화면 회전과 같은 변경사항이 발생해 액티비티나 프래그먼트가 다시 생성되어도 사용 가능한 최신 데이터를 즉시 받을 수 있기 때문에 화면이 회전되는 것을 신경쓰지 않아도 된다.

다만 단점을 꼽자면 RxJava처럼 데이터 스트림을 결합하거나 스레드를 관리하기 위한 도구 키트가 함께 제공되지 않고, 기능이 제한적이라는 점, 실행중인 컨텍스트를 제어하기 힘들다는 점, 잘못 사용할 시 많은 보일러 플레이트 코드가 발생할 수 있다는 점 등등이 있겠다.

LiveData & ViewModel


다음은 AAC(Android Architecture Component, MVVM 패턴을 좀 더 쉽게 구현할 수 있도록 안드로이드에서 제공하는 라이브러리)의 전체적인 흐름을 나타낸 그림이다. 액티비티나 프래그먼트는 ViewModel의 LiveData를 통해 ViewModel이 홀딩하고 있는 데이터의 변경을 실시간으로 관찰할 수 있으며, 변경이 감지되면 곧바로 화면에 업데이트 할 수 있다.

class ViewModel(private val dao : Dao) : ViewModel(){

    fun getAll() : LiveData<List<DataModel>> 
    					= dao.getAll()

}
class MainActivity : AppCompatActivity() {

    private val model: ViewModel by inject()

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)

        	viewModel.getAll().observe(this, Observer {
            // // db에 저장된 값이 변경되면 LiveData로 실시간 감지 가능
        })
    }
}

LiveData 사용

LiveData 관찰

LiveData는 UI 작업을 할 때 주로 사용한다. 액티비티나 프래그먼트가 활성화되는 즉시 데이터를 표시하기 위해, 또는 onResume()에서 중복 호출을 하지 않기 위해 액티비티의 경우에는 onCreate(), 프래그먼트의 경우에는 onViewCreated()에서 LiveData를 관찰한다.

LiveData 관찰 시 observe()를 사용하고, 인자로 LifecycleOwner, Observer를 전달한다. observe()는 LifeCycleOwner로 해당 컴포넌트의 생명주기를 인식하고, 주어진 생명 주기 내에서 지정된 Observer를 Observer 리스트에 추가한다.

class MainActivity : AppCompatActivity() {

	private lateinit var binding : ActivityMainBinding
    private val model: ViewModel by inject()

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        binding = ActivityMainBinding.inflate(layoutInflater)
        setContentView(binding.root)

        viewModel.get().observe(this, Observer {
        	binding.nameTextView.text = it.text
        })
    }
}

LiveData vs MutableLiveData

LiveData는 값의 조회만 가능하지만, MutableLiveData는 값을 조회할 뿐만 아니라 변경할 수도 있다. 따라서 목적에 맞게 사용하면 되는데, 이렇게 나눠서 사용하는 이유는 ViewModel과 View의 역할을 분리하기 위해서라고 한다. ViewModel은 언제나 새로운 값이 업데이트되고, 업데이트된 값을 읽기 위해 사용하지만, View에서는 ViewModel에서 변경된 값을 읽어오기만 하면 되기 때문이다. 하지만 이게 원칙은 아니니, 상황에 맞게 잘 사용하는 것이 베스트다.

LiveData는 값을 조회하기 위해 getValue()를, 값을 변경하기 위해 setValue(), postValue()를 제공한다. setValue()와 postValue()는 값 변경을 메인 스레드에서 하느냐, 백그라운드에서 하느냐에 차이가 있다.

setValue() : 메인 스레드에서 LiveData의 값을 변경해준다. 메인 스레드에서 바로 값을 변경해주기 때문에 setValue() 함수를 호출한 직후 getValue()로 값을 읽어오면 변경된 값을 가져올 수 있다.

postValue() : 백그라운드 스레드에서 LiveData의 값을 변경해준다. 백그라운드 스레드에서 동작하다가 메인 스레드에 값을 post하는 방식으로 사용하는데, 메인 스레드에 적용되기 전에 postValue()가 여러번 호출된다면 모든 값이 적용되는 것이 아니라 가장 최신의 값이 적용된다. 따라서 postValue()를 호출한 뒤 바로 getValue()로 값을 읽으려고 하면 변경된 값을 읽어오지 못할 가능성이 높다.

References

https://developer.android.com/topic/libraries/architecture/livedata?hl=ko
https://logidots.com/insights/live-data-flow-shared-flow-state-flow-2/
https://thdev.tech/android/2021/02/01/LiveData-Intro/
https://leveloper.tistory.com/179

profile
Flutter Developer

0개의 댓글