Kerubyte
Kerubyte

Reputation: 27

Why return function in variable is null? Kotlin + Android

I am missing some basic coding knowledge here I think, I want to present value to the fragment by assigning the function to the variable in a viewModel. When I call the function directly, I get correct value. When I assign function to variable and pass the variable to the fragment it is always null, why?

View Model

class CartFragmentViewModel : ViewModel() {

    private val repository = FirebaseCloud()
    private val user = repository.getUserData()

    val userCart = user?.switchMap {
        repository.getProductsFromCart(it.cart)
    }

    private fun calculateCartValue(): Long? {
        val list = userCart?.value
        return list?.map { it.price!! }?.sum()

    }
     //val cartValue = userCart?.value?.sumOf { it.price!! } <- THIS will be null
    val cartValue = calculateCartValue() <- THIS will be null
    val cartSize = userCart?.value?.size <- THIS will be null
}

Fragment

class CartFragment : RootFragment(), OnProductClick, View.OnClickListener {

    private lateinit var cartViewModel: CartFragmentViewModel
    private lateinit var binding: FragmentCartBinding
    private val cartAdapter = CartAdapter(this)

    override fun onCreateView(
        inflater: LayoutInflater, container: ViewGroup?,
        savedInstanceState: Bundle?
    ): View {
        binding = DataBindingUtil.inflate(
            inflater,
            R.layout.fragment_cart,
            container,
            false
        )
        setAnimation()

        cartViewModel = CartFragmentViewModel()
        binding.buttonToCheckout.setOnClickListener(this)
        return binding.root
    }

    override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
        super.onViewCreated(view, savedInstanceState)
        binding.recyclerCart.apply {
            layoutManager = LinearLayoutManager(requireContext())
            adapter = cartAdapter
        }
        cartViewModel.userCart?.observe(viewLifecycleOwner, { list ->
            cartAdapter.setCartProducts(list)

            updateCart()
        })
    }

    override fun onClick(view: View?) {
        when (view) {
            binding.buttonToCheckout -> {
                navigateToCheckout(cartViewModel.cartValue.toString())
                cartViewModel.sendProductEvent(
                    cartAdapter.cartList,
                    ProductEventType.CHECKOUT
                )
            }
        }
    }

    override fun onProductClick(product: Product, position: Int) {
        cartViewModel.removeFromCart(product)
        cartAdapter.removeFromCart(product, position)

        updateCart()
    }

    private fun updateCart() {
        binding.textCartTotalValue.text = cartViewModel.cartValue.toString() <- NULL
        binding.textCartQuantityValue.text = cartViewModel.cartSize.toString() <- NULL
    }
}

Thanks!

Upvotes: 1

Views: 596

Answers (1)

Henry Twist
Henry Twist

Reputation: 5980

It looks like userCart is some sort of observable variable which initially holds a null value and then gets populated with the data from your repository after the network call (or something similar) completes.

The reason that all your variables are null are because you are declaring their value immediately, so by the time those statements get executed, the network call hasn't yet completed and userCart?.value is null. However calling the calculateCartValue() function later on in the code might yield a value if the fetch is complete.

Upvotes: 1

Related Questions