반응형

오늘은 안드로이드의 MVVM 패턴의 핵심이라고 할 수 있는 ViewModel에 대해 알아보려고 한다.

학습내용

  • ViewModel의 개념
  • ViewModel과 생명주기
  • ViewModel의 사용목적
  • 직접 ViewModel 사용해보기

 

ViewModel

  • UI관련 데이터 저장 및 UI로직을 처리 및 관리하기 위해 만들어짐
  • LifeCycle 패키지에 포함된 것에서 알 수 있듯이 생명주기를 고려해서 동작하도록 구현됨

 

ViewModel과 생명주기

  • View의 생명주기는 안드로이드 FrameWork에 의해 관리됨
  • 화면 회전이나 글씨 크기 변경 등 구성 변경 발생시 View는 Destroy되고 다시 재생성
  • ViewModel은 View의 Lifecycle에 scoping되어 View가 완전히 종료될 때 까지
  • 객체가 유지됨
  • View -> ViewModel -> Repository의 구조로 의존성이 단방향으로만 생성
  • UI데이터 저장과 로직 처리를 View에서 분리함

 

ViewModel의 사용 목적

  • View는 최대한 모르게. 멍청하게(?)
  • Android의 까다로운 View 생명주기 때문에 실수하기 쉬운 코드를 예방할 수 있음
  • 테스트 코드 작성이 간편해짐
  • 동일한 Activity에 attach된 Fragment간 데이터 공유가 편리함

 

ViewModel 사용해보기

ViewModel을 사용하기 위해 먼저 implementation를 추가하자.

implementation 'androidx.lifecycle:lifecycle-viewmodel-ktx:2.3.1' (최신버전에 맞춰 수정)


그리고 다음과 같이 viewModel 변수를 정의하여 사용할 준비를 한다.

private val viewModel: MainViewModel by lazy{
	// onCreate 이후에 호출되어야 함
	ViewModelProvider(this)[MainViewModel::class.java]
}

ViewModel 객체는 이렇게 ViewModelProvider를 통해 받아야 한다.

 

ViewModel 사용 전과 후의 코드 비교

<전>

class MainActivity : AppCompatActivity() {
    private lateinit var binding: ActivityMainBinding
    private val count = 0L

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

        setContentView(binding.root)
        initViews()
    }

    private fun initViews() {
        binding.increaseButton.setOnClickListener {
            count++
            binding.countText.text = count.toString()
        }
    }
}

<후>

class MainActivity : AppCompatActivity() {
    private lateinit var binding: ActivityMainBinding

    private val viewModel: MainViewModel by lazy{
        ViewModelProvider(this)[MainViewModel::class.java]
    }

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

        setContentView(binding.root)
        initViews()
    }

    private fun initViews() {
        binding.increaseButton.setOnClickListener {
            viewModel.increaseCount()
        }
        viewModel.count.observe(this) {
            binding.countText.text = it.toString()
        }
    }
}

class MainViewModel: ViewModel() {
    private val _count = MutableLiveData<Long>().apply {
        value = 0
    }
    
    val count: LiveData<Long>
        get() = _count

    fun increaseCount() {
        _count.value = (count.value ?: 0) + 1
    }
}
 

<전>과 <후>의 코드를 보면 알 수 있듯이

ViewModel을 이용하면 View가 직접 데이터 처리를 하지 않는다.

 

데이터의 저장과 로직 처리는 모두 ViewModel에서 이루어지고 있고,

View는 뷰모델을 observe하다가 변화가 일어나면 단지 view를 업데이트 하는 역할을 한다.

 

즉, 그동안 View에서 UI 데이터의 저장과 로직처리를 모두 했다면

이 역할을 ViewModel로 분리시킨 것이다.

반응형

+ Recent posts