title: What is the correct way to observer LiveData?
body: <p>Suppose there's a LiveData object in a ViewModel whose content is of interest of multiple views. Each view is handled differently and may or may not be displayed at any given time, independent of the other views.</p>
  
  <p>Which of these approaches is better/correct?</p>
  
  <ol>
  <li><p>To have 1 observer to such LiveData object, and have the observer to implement the update logic for all views, making the necessary checks, etc.</p></li>
  <li><p>To have multiple observers to the LiveData object (or per interested view) and each observer only deals with the logic of that particular view.</p></li>
  </ol>
  
  <p>What I have noticed so far is that following option 1 can lead to code that is difficult to manage and understand. The same view may be updated in different parts of the code, which reduces readability. Option 2 solves that problem by allowing all code related to a view to be colocated. However, I'm concerned about the performance penalty of having multiple observers on the same LiveData in the same Fragment.</p>
  
  <p>Which one is the most appropriate approach for complex views?</p>
  
  <p>Example:</p>
  
  <pre><code>class NewViewModel() : ViewModel() {
      private val _lv1 = MutableLiveData&lt;Boolean&gt;(false)
      val lv1: LiveData&lt;Boolean&gt; = _lv1
  
      private val _lv2 = MutableLiveData&lt;Boolean&gt;(false)
      val lv2: LiveData&lt;Boolean&gt; = _lv2
  }
  
  class NewFragment : Fragment() {
  
      private var _viewBinding: FragmentNewBinding? = null
      private val viewBinding
          get() = _viewBinding!!
  
      private val viewModel by viewModels&lt;NewViewModel&gt; { getViewModelFactory() }
  
      override fun onCreateView(...): View? {
          _viewBinding = FragmentNewBinding.inflate(inflater)
  
          return viewBinding.root
      }
  
      override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
          super.onViewCreated(view, savedInstanceState)
  
          example1()
  
          example2_1()
          example2_2()
      }
  
      override fun onDestroyView() {
          _viewBinding = null
  
          super.onDestroyView()
      }
  
     private fun example1() {
          val view1 = viewBinding.view1
          viewModel.lv1.observe(viewLifecycleOwner, Observer {
              // Some complex-ish UI logic that might need
              // to retrieve supplement data from somewhere (e.g Glide)
              view1.refreshWith(it)
          })
  
          val view2 = viewBinding.view2
          viewModel.lv1.observe(viewLifecycleOwner, Observer {
              // Some complex-ish UI logic that might need
              // to retrieve supplement data from somewhere (e.g Glide)
              view2.refreshWith(it)
          })
      }
  
      private fun example2_1() {
          val view1 = viewBinding.view1
  
          viewModel.lv2.observe(viewLifecycleOwner, Observer {
              // Some complex-ish UI logic that might need
              // to retrieve supplement data from somewhere (e.g Glide)
              view1.refreshWith(it)
          })
      }
  
      private fun example2_2() {
          val view2 = viewBinding.view2
  
          viewModel.lv2.observe(viewLifecycleOwner, Observer {
              // Some complex-ish UI logic that might need
              // to retrieve supplement data from somewhere (e.g Glide)
              view2.refreshWith(it)
          })
      }
  }
  </code></pre>