簡體   English   中英

在 Kotlin Android 中,viewModel 沒有觀察者

[英]In Kotlin Android, viewModel has no observer

我在一個BaseActivity中做了一個工具欄來實現一個通用的,代碼如下。

// BaseActivity
abstract class BaseActivity<T : ViewBinding> : AppCompatActivity() {
    lateinit var cartCnt: TextView

    private val viewModel by lazy {
        ViewModelProvider(this, CartViewModelFactory())[CartViewModel::class.java]
    }

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        binding = DataBindingUtil.setContentView(this, layoutId)
        mContext = this

        viewModel.cartItemList.observe(this){
            cartCnt.text = it.size.toString()
        }

        supportActionBar?.let {
            setCustomActionBar()
        }

    }
    open fun setCustomActionBar() {

        val defActionBar = supportActionBar!!
        defActionBar.elevation = 0F
        defActionBar.displayOptions = ActionBar.DISPLAY_SHOW_CUSTOM
        defActionBar.setCustomView(R.layout.custom_action_bar)

        val toolbar = defActionBar.customView.parent as Toolbar
        toolbar.setContentInsetsAbsolute(0, 0)
        cartCnt = defActionBar.customView.findViewById(R.id.cartCnt)

    }

}

在 BaseActivity 中,從 CartView Model 中的 MutableLiveData 中觀察到名為 cartCnt(當前購物車中的產品數量)的 TextView 的文本。

如下:cartviewmodel

// CartViewModel
class CartViewModel() : ViewModel() {

    private val list = mutableListOf<Cart>()
    private val _cartItemList: MutableLiveData<List<Cart>> = MutableLiveData()
    val cartItemList: LiveData<List<Cart>> get() = _cartItemList


    private val repository by lazy {
        CartRepository.getInstance()
    }

    init {
        getAllCartItems()
    }


    fun getAllCartItems() {
        viewModelScope.launch {
            repository!!.getRequestMyCartList {
                if (it is Result.Success) {
                    list.addAll(it.data.data!!.carts)
                    _cartItemList.value = list
                }
            }

        }
    }

    fun addToCartItem(id: Int) {
        viewModelScope.launch {
            repository!!.postRequestAddCart(id) {
                if (it is Result.Success) {
                    list.add(it.data.data!!.cart)
                    _cartItemList.value = list
                }
            }

        }
    }
}

View Model 的觀察者只存在於 SplashActivity,它首先繼承了 BaseActivity。 (驗證為 function hasObservers。)。

當我在產品列表頁面點擊購物籃按鈕時,與服務器通信,確認購物籃數據正常放入服務器表中,也確認正常返回200狀態碼。

但是,當有產品列表頁面的 Fragment 聲明 cartViewModel 並調用 addToCartItem function 時,cartViewModel 上沒有附加觀察者。 這是通過hasObservers function確認的部分。

視圖結構大致有MainActivity繼承自BaseActivity,TodayFragment存在於MainActivity中。

而且,TodayFragment 的代碼如下。

// TodayFragment
class TodayFragment : BaseFragment<FragmentTodayBinding>() {

    override val layoutId: Int = R.layout.fragment_today
    private lateinit var bannerViewPager: BannerRecyclerviewAdapter
    private lateinit var productAdapter: ProductHorizonRecyclerviewAdapter

    private val cartViewModel by lazy {
        ViewModelProvider(this, CartViewModelFactory())[CartViewModel::class.java]
    }

    override fun init() {

    }

    override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
        super.onViewCreated(view, savedInstanceState)

        initProductRecyclerview()
        setValues()
    }

    override fun setValues() {
        HomeViewModel.currentPosition.observe(viewLifecycleOwner) {
            binding.bannerViewpager.currentItem = it
        }
    }


    private fun initProductRecyclerview(){
        binding.productRecyclerView.apply {
            productAdapter = ProductHorizonRecyclerviewAdapter(){
                cartViewModel.addToCartItem(it.id)
            }
            adapter = productAdapter
            layoutManager = LinearLayoutManager(requireContext(), LinearLayoutManager.HORIZONTAL, false)
        }

    }

}

也就是說,當通過TodayFragment中的商品列表頁面調用cartViewModel的addToCartItem function時,cartViewModel的mutableLiveData發生了變化,BaseActivity的cartCnt TextView正在觀察這個變化。

在這種情況下,我想知道為什么第一個SplashActivity,出現在activity棧結構中,有observer,然后在Today Fragment中消失了。

來人幫幫我。

您正在 TodayFragment 中通過向它傳遞一個工廠來重新創建 cartViewModel,這就是它沒有 BaseActivity 觀察器的原因。 在 TodayFragment 中試試這個

private val cartViewModel: CartViewModel by activityViewModels()

或者

private val cartViewModel by lazy {
    ViewModelProvider(requireActivity())[CartViewModel::class.java]
}

然后,如果您在 TodayFragment 中調用cartViewModel.addToCartItem() ,它應該在 BaseActivity 中調用觀察者。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM