[Android] Jetpack 알아보기 (1) - LiveData, ViewModel

moKo·2021년 10월 12일
0

Android

목록 보기
4/13
post-thumbnail

개발하는 정대리님 유튜브를 통해 공부한 내용입니다.

🚀 Jetpack이란?

jetpack이란 안드로이드 공식문서에 따르면 개발자가 모범사례를 따르고, 상용구 코드를 줄이며, android 버전 및 기기에서 일관되게 작동하는 코드를 작성하여 개발자가 관심있는 코드에 집중할 수 있도록 도와주는 라이브러리 모음이라고 나와있다.

jetpack을 사용하는 이유는 다양하다. 현대적 디자인을 기반으로 구축되어 이전 버전과의 호환성을 통해 충돌을 줄이고 메모리 누수를 줄여준다. 또한 백그라운드 작업, 탐색 및 수명 주기 관리와 같은 지루한 활동을 관리하므로 집중이 필요한 요소를 더욱 훌륭하게 만들게 도와준다

ViewModel

ViewModel은 기존의 생명주기에 따라 움직이는 개발 방식과는 달리 생명주기를 상관하지 않고 항시 살아있는 클래스이다. 단지 종료시에만 onCleared()를 통해 메모리 정리가 이루어진다.

ViewModel 구현하기

viewModel을 사용하기 위해선 gradle 설정이 필요하다.

implementation("androidx.lifecycle:lifecycle-viewmodel-ktx:$lifecycle_version")

LiveData

LiveData는 observable 데이터 홀더 클래스이다. 일반적인 observable과는 다르게 생명 주기를 인식한다. 즉, 활동, 프래그먼트, 서비스 등 다른 앱 구성요소의 생명 주기를 고려한다. 생명 주기 인식을 통해 활동 수명 주기 상태에 있는 앱 구성 요소의 observer만을 업데이트 한다. 즉 acive 상태에 있으면 항상 업데이트 한다는 것이다.

LifecycleOwner 라는 클래스를 가지며 유일한 메소드로 getLifecycle()을 갖는데 이를 통해 현재 생명주기를 알아온다.

LiveData를 왜쓸까?

1. UI와 데이터 상태의 일치를 보장한다.
-> livedata는 observer 패턴을 따른다. 그렇기 때문에 기본 데이터가 변경되면 observer 객체에 알려주고 이 observer 패턴이 데이터 변화가 일어나는 ui에 따로 코드가 필요없이 빠르고 정확하게 업데이트 해주어 데이터 상태와 ui가 항상 일치하게 보장해준다.
2. 메모리 누수가 없다.
-> observer는 lifecycle 객체에 결합되어있고 연결된 생명 주기가 끝나면(destroy) 자동으로 삭제된다.
3. 중지된 활동으로 인한 비정상 종료가 없다.
-> 액티비티가 백그라운드에 있거나, observer의 생명주기가 비활성 상태에 있으면 어떤 livedata 이벤트도 받지 않는다.
4. 생명 주기를 더 이상 수동으로 처리하지 않는다.
-> UI 구성요소는 관련데이터를 관찰하기만 할 뿐 중지하거나 다시 시작하지 않는다. 관찰하는 동안 관련 생명 주기 상태의 변경을 인식하므로 이 모든 것을 자동으로 관리한다.
5.최신 데이터 유지
-> 생명 주기가 비활성에서 활성으로 넘어올 때, 최신 데이터를 수신한다.
6.자원을 공유할 수 있다.
-> LiveData를 상속하여 따로 임의의 클래스를 구현할 수 있고, 싱글톤 패턴을 이용하여 앱 어디서나 자원을 공유할 수 있다.

LiveData 구현하기

LiveData를 사용하기 위해선 gradle 설정이 필요하다.

implementation("androidx.lifecycle:lifecycle-livedata-ktx:$lifecycle_version")

ViewModel, LiveData 사용법

간단한 예시로 덧셈과 뺄셈 기능만을 수행하는 계산기를 만들어보자

MyNumberViewModel.kt

import androidx.lifecycle.LiveData
import androidx.lifecycle.MutableLiveData
import androidx.lifecycle.ViewModel

// 두 가지 액션타입 생성
enum class ActionType {
    PLUS, MINUS
}

// 데이터의 변경을 가짐
// 뷰모델은 데이터의 변경사항을 알려주는 라이브데이터를 가진다
class MyNumberViewModel : ViewModel() {

    // mutable 라이브 데이터 - 수정가능
    // 라이브 데이터 - 값 변동 안됨

    // 내부에 생성하는 데이터는 mutable로
    // 변경 가능하도록 설정
    private val _currentValue = MutableLiveData<Int>()

    // 변경되지 않는 데이터를 가져 올때 이름을 _ 언더스코어 없이 설정
    // 공개적으로 가져오는 변수는 private이 아닌 퍼블릭으로 외부에서도 접근 가능하도록 설정
    // 하지만 값을 직접 라이브 데이터에 접근하지 않고, 뷰모델을 통해 가져올 수 있도록 설정
    val currentValue: LiveData<Int>
        get() = _currentValue

    // 초기값 설정
    init {
        _currentValue.value = 0
    }
	// 액션타입에 따른 update
    fun updateValue(actionType: ActionType, input: Int) {

        when (actionType) {
            ActionType.PLUS ->
                _currentValue.value = _currentValue.value?.plus(input)
            ActionType.MINUS ->
                _currentValue.value = _currentValue.value?.minus(input)
        }
    }
}

MainActivity.kt

import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import android.view.View
import androidx.lifecycle.Observer
import androidx.lifecycle.ViewModelProvider
import kotlinx.android.synthetic.main.activity_main.*

class MainActivity : AppCompatActivity(), View.OnClickListener {

    lateinit var myNumberViewModel: MyNumberViewModel

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)
        
        // viewmodelprovider를 통해 viewmodel을 가져온다
        myNumberViewModel = ViewModelProvider(this).get(MyNumberViewModel::class.java)

        // viewmodel의 livedata에 접근후 observe로 관찰
        myNumberViewModel.currentValue.observe(this, Observer {
        	// 값이 변경되는데로 바로바로 적용
            number_textview.text = it.toString()
        })

        // connect listener
        plus_btn.setOnClickListener(this)
        minus_btn.setOnClickListener(this)
    }

    // 클릭
    override fun onClick(view: View?) {
        val userInput = userinput_edittext.text.toString().toInt()

        when(view) {
            plus_btn ->
                myNumberViewModel.updateValue(actionType = ActionType.PLUS, userInput)
            minus_btn ->
                myNumberViewModel.updateValue(actionType = ActionType.MINUS, userInput)
        }
    }
}

profile
🔥 Feelings fade, results remain

0개의 댓글