Search code examples
androidmvvmandroid-architecture-componentsandroid-navigationandroid-architecture-navigation

SharedViewModel instance does not recover data from original instance


I have one fragment where I update a total integer in my sharedViewModel, this is the shopsFragment

class ShopFragment : Fragment(), AppBarLayout.OnOffsetChangedListener {

    private val model: SharedViewModel by viewModels()

  override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
        super.onViewCreated(view, savedInstanceState)
        model.updateTotal(200)
    }
}

Now, my other fragment that I need this data to be shared between, is a BottomSheetDialogFragment , in this Fragment I get an instance of the sharedViewModel by doing this

class CartBottomSheet: BottomSheetDialogFragment() {

    private val model: SharedViewModel by viewModels ({requireParentFragment()})

 override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
        super.onViewCreated(view, savedInstanceState)
          model.getTotal().observe(viewLifecycleOwner, Observer { total ->
            sheet_total_price.text = "$$total.00"
        })
    }

Now, when I try to get the 200 that I posted in the other Fragment, it shows 0, and that means that the instance of that sharedViewModel is a new instance because it returns 0 because my viewmodel instance initializes a common shared total with 0

class SharedViewModel: ViewModel() {
    private val totalData = MutableLiveData<Int>()
    private var sharedTotal = 0

 fun updateTotal(total:Int){
        sharedTotal = total
        totalData.value = sharedTotal
    }

    fun getTotal():LiveData<Int>{
        return totalData
    }

Now, my question is, do I need to pass as a bundle to the BottomDialogFragment this instance of the sharedViewmodel to work with, or is there any way to get the same instance to get the value of total

Thanks


Solution

  • You can set ShopFragment as targetFragment for the CartBottomSheet fragment. In this way when you create the Shared VM you will get the same instance. Basically if you put this together you can achieve it by the code below :-

    class CartBottomSheet: BottomSheetDialogFragment() {
        private val model: SharedViewModel?=null
    
        companion object {
            fun show(fragmentManager: FragmentManager, parentFragment: Fragment) {
                val sheet = CartBottomSheet()
                sheet.setTargetFragment(parentFragment, 13)
                sheet.show(fragmentManager, sheet.tag)
            }
        }
        override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
            super.onViewCreated(view, savedInstanceState)
            targetFragment?.let {
                // Create model here with it 
            }
        }
    
    }
    

    So now for opening sheet you should call

    CartBottomSheet.show(fragmentManager!!, this)