What's ViewModel

💀LeeSY·2022년 8월 4일
1

Jetpack

목록 보기
1/1
post-thumbnail

ViewModel??

  • Android Jetpack 구성 요소 중 하나로서, MVVM 패턴에서 파생되었다.
  • LifeCycle을 고려하여 UI 관련 데이터를 저장하고, 관리하도록 설계된 클래스.
  • 화면 회전 같은 구성 변경 시에도 데이터 유지 가능
  • UI 컨트롤러의 데이터를 캡슐화하여 구성이 변경되더라도 데이터를 유지하는 것이 ViewModel의 주 목적이다.
  • 비동기 호출 시 리소스 관리를 위한 요소가 필요하다. 따라서 ViewModel에서는 Coroutine 지원이 포함된다.
viewModelScope.launch {
	//TODO asynchronous
}
  • Viewmodel 기반 아키텍처 패턴을 적용함으로서, Activity나 Fragment의 과도한 코드 확장을 방지하고, 유지보수, 재사용성을 높일 수 있다.

ViewModel-LifeCycle

  • 일반적으로 알고 있는 Activity나 Fragment의 생명주기와 ViewModel의 생명주기는 차이가 있다.

  • Activity 생성 시 ViewModel을 인스턴스화하여 생명주기가 함께 시작된다.

  • Activity의 경우에는 구성 변경이 일어날 때 재시작하는 것을 확인할 수 있으나, ViewModel의 경우에는 메모리 상에 계속 유지된다.

  • ViewModel은 Activity의 구성 변경과는 무관하게 유지되는 NonConfigurationInstances 객체를 따로 관리하기 때문이다.

  • Activity의 생명주기가 finish()를 통해 실질적으로 종료됨에 따라 내부의 LifeCycleEventObserver를 통해 ViewModel도 onCleared()를 통해 같이 종료된다.

ViewModel Process


1. ViewModelProvider를 통해 ViewModel 인스턴스를 요청한다.
2. Provider 내부에서는 ViewModelStoreOwner를 참조하여 ViewModelStore를 가져온다.
3. ViewModelStore에게 생성 또는 저장된 ViewModel 인스턴스를 요청한다.
4. 만일 ViewModelStore가 적합한 ViewModel 인스턴스를 갖고 있지 않다면, Factory를 통해 ViewModel 인스턴스를 생성한다.
5. 생성한 ViewModel 인스턴스를 Store에 저장하고 해당 인스턴스를 Client에게 반환한다.

ViewModel Example - Activity

/*
currentName 이라는 변수가 값을 Observe할 대상으로 만들어질 것이다.
여기에서 MutableLiveData 라는 클래스가 쓰였는데, 
이 클래스는 Observer Pattern과 비슷한 역할을 가지는 클래스이다.
ViewModel에서 사용하는 데이터는 이 클래스의 생성자를 통해 만든다고 이해하면 된다.
 */
class NameViewModel : ViewModel() {
    val currentName : MutableLiveData<String> by lazy {
        MutableLiveData<String>()
}
.
.
.
class MainActivity : AppCompatActivity() {

    private lateinit var model : NameViewModel
    private lateinit var binding : ActivityMainBinding

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        binding = DataBindingUtil.setContentView(this, R.layout.activity_main)

        model = ViewModelProvider(this).get(NameViewModel::class.java)
        binding.name = model

        model.currentName.observe(this, Observer {
            binding.textOutput.text = it.toString()
        })

        binding.btnSave.setOnClickListener {
            binding.textOutput.text = binding.editName.text.toString()
            binding.editName.text.clear()
        }
    }
}
  • ViewModel을 생성하기 위해서는 ViewModel Provider 객체가 필요하다.
  • 일반적으로 ViewModelProvider의 생성하기 위해 생성자 매개변수로 ViewModelStoreOwner와 ViewModelProvider.Factory가 필요하다.

ViewModel Example - Fragment

  • 같은 LifeCycleOwner를 설정해야 Fragment 간의 데이터 공유가 가능하다.
class MyViewModel : ViewModel() { 
   val message = MutableLiveData<String>() 
   fun sendMessage(text: String) { 
      message.value = text 
   } 
}
.
.
.
//ViewModel 데이터 업데이트
class FirstFragment : Fragment() {
    lateinit var model: MyViewModel
    //...    
    override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
        super.onViewCreated(view, savedInstanceState)
        model = ViewModelProvider(requireActivity()).get(MyViewModel::class.java)
        button.setOnClickListener { model.sendMessage("MindOrks") }
    }
}
.
.
.
//ViewModel 데이터 Detecting
class SecondFragment : Fragment() { 
     // ... 
     override fun onViewCreated(view: View, savedInstanceState: Bundle?) { 
     super.onViewCreated(view, savedInstanceState) 
     val model = ViewModelProvider(requireActivity()).get(MyViewModel::class.java) 
     model.message.observe(viewLifecycleOwner, Observer { textViewReceiver.text = it }) 
     } 
}
  • ViewModel 생성 시 Owner 파라미터에 requireActivity()를 사용해야 상위 Activity를 Owner로 설정하는 특징을 통해 서로 다른 Fragment가 같은 Owner를 바라볼 수 있도록 해줄 수 있다.

참고 자료 :

profile
A little strange but passionate, sincere hard worker.

0개의 댓글

관련 채용 정보