ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • Android Kotlin Fundamentals - ViewModel(2)
    Android 2021. 5. 30. 09:37

    Activity ViewModel을 활용한 Fragment 간 데이터 공유

    • Fragment가 N 개인데, Data의 공유가 필요한 경우
    • Fragment에서 처리한 데이터에 따라 Activity의 데이터 갱신이 필요한 경우

    보통 위와 같은 이유로 sharedViewModels를 사용하는 케이스가 있다.

    1. fragment-ktx를 사용하지 않을 경우

    SharedViewModel, Fragment들을 아래와 같이 간단하게 구현

    class SharedViewModel : ViewModel() {
        val message = MutableLiveData<String>()
        fun sendMessage(msg:String){
            message.value = msg
        }
    }
    class MessageReceiverFragment:Fragment() {
        private val model by lazy {
            ViewModelProvider(requireActivity(), object : ViewModelProvider.Factory {
                override fun <T : ViewModel?> create(modelClass: Class<T>): T {
                    return SharedViewModel() as T
                }
            }).get(SharedViewModel::class.java)
        }
    
        override fun onCreateView(
            inflater: LayoutInflater,
            container: ViewGroup?,
            savedInstanceState: Bundle?
        ): View {
            val binding:FragmentReceiverBinding = DataBindingUtil.inflate(
                inflater, R.layout.fragment_receiver, container, false)
    
            model.message.observe(viewLifecycleOwner, Observer {
                binding.textViewReceiver.text = it
            })
    
            return binding.root
        }
    class MessageSenderFragment:Fragment() {
        private val model:SharedViewModel by lazy {
            ViewModelProvider(requireActivity(),
                object : ViewModelProvider.Factory {
                    override fun <T : ViewModel?> create(modelClass: Class<T>): T {
                        return SharedViewModel() as T
                    }
                }).get(SharedViewModel::class.java)
        }
    
        override fun onCreateView(
            inflater: LayoutInflater,
            container: ViewGroup?,
            savedInstanceState: Bundle?
        ): View? {
            val binding:FragmentSenderBinding = DataBindingUtil.inflate(
                inflater, R.layout.fragment_sender, container, false
            )
            binding.button.setOnClickListener {
                model.sendMessage("ViewModel TEST")            
            }
            return binding.root
        }

    SharedViewModel을 인스턴스를 얻을 때 ViewModelProvider의 첫번째 생성자 매개변수인 ViewModelStoreOwner를 Fragment들이 속해있는 부모 Activity로 지정하자. 그러면 각 프레그먼트는 동일한 SharedViewModel 인스턴스를 얻게 된다. SharedViewModel의 생명주기는 Activity를 따르게 되고, Fragment의 생명주기는 Activity의 서브셋이므로 Fragment의 생명주기 동안에 자유롭게 데이터를 공유할 수 있게 된다.

    2. fragment-ktx를 사용할 경우

    아래와 같이 activityViewModels를 사용하여 정의한다.

        private val sharedModel by activityViewModels<SharedViewModel> {
            object : ViewModelProvider.Factory{
                override fun <T : ViewModel?> create(modelClass: Class<T>): T
                    = SharedViewModel() as T
            }
        }

    Activity범위내에서 ViewModel을 공유하여 프레그먼트가 데이터를 공유하는 경우 다음과 같은 장점이 있다. 

    • Activity는아무것도 할 필요가 없거나 Fragment 커뮤니케이션에 관해 알 필요가 없다
    • Fragment는 SharedViewModel외에 다른 부분에 대해서 서로 알 필요가 없다. Fragment 중 하나가 사라져도 다른 프레그먼트는 평소처럼 동작한다.
    • 각 Fragment는 자체 생명주기를 가지고 있고, 다른 Fragment의 생명주기에 영향을 주거나 받지 않는다. 한 Fragment가 다른 Fragment를 대체해도 UI는 아무 문제 없이 계속 작동한다.

     

    References

    'Android' 카테고리의 다른 글

    LiveData beyond the ViewModel  (0) 2021.06.04
    LiveData  (0) 2021.05.30
    Android Kotlin Fundamentals - ViewModel(1)  (0) 2021.05.29
    ViewModel  (0) 2021.05.28
    Navigation Component(2)  (0) 2021.05.19
Designed by Tistory.