Search code examples
androidkotlinandroid-recyclerviewlistadapter

Android: ListAdapter.Currentlist.isEmpty() is showing true even tho list is not empty


My problem is that when I write MyListAdapter.currentList.isEmpty() the value is true even tho the list is NOT EMPTY! (I can see it in my view and in my database). What am I doing wrong, why is the value true even tho it should be false?

Fragment

@AndroidEntryPoint
class ShoppingCartFragment(
    private val cacheMapper: ShopCacheMapper
) : Fragment(R.layout.fragment_shopping_cart), ShoppingCartListAdapter.OnItemClickListener {
    private val shoppingCartViewModel: ShoppingCartViewModel by viewModels()
    private val shoppingCartBinding: FragmentShoppingCartBinding by viewBinding()
    @Inject lateinit var shoppingCartAdapter: ShoppingCartListAdapter

    override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
        super.onViewCreated(view, savedInstanceState)
        bindObjects()
        observeList()
        hideBtnIfListEmpty()
        toast("LISTE IST EMPTY: ${shoppingCartAdapter.currentList.isEmpty()}")
    }

    private fun observeList() {
        shoppingCartViewModel.productList.observe(viewLifecycleOwner) {
            shoppingCartAdapter.submitList(it)
        }
    }

    private fun bindObjects() = with(shoppingCartBinding) {
        adapter = shoppingCartAdapter.apply { clickHandler(this@ShoppingCartFragment) }
        viewModel = shoppingCartViewModel
        lifecycleOwner = viewLifecycleOwner
    }

    override fun forwardCardClick(productCacheEntity: ProductCacheEntity) {
        val product = cacheMapper.mapFromEntity(productCacheEntity)
        val action = ShoppingCartFragmentDirections.actionShoppingCartFragmentToShopItemFragment(product)
        findNavController().navigate(action)
    }

    override fun fordwardBtnIncreaseClick(id: Int) {
        shoppingCartViewModel.increaseProductQuantityById(id)
    }

    override fun fordwardBtnDecreaseClick(id: Int) {
        shoppingCartViewModel.decreaseProductQuantityById(id)
    }

    override fun forwardBtnDeleteClick(id: Int) {
        shoppingCartViewModel.deleteProductById(id)
    }

    override fun onDestroyView() {
        requireView().findViewById<RecyclerView>(R.id.rv_shopping_cart).adapter = null
        super.onDestroyView()
    }

    // here lies the problem
    private fun hideBtnIfListEmpty() {
        if (shoppingCartAdapter.currentList.isEmpty()) shoppingCartBinding.shoppingCartBtn.root.visibility = View.INVISIBLE
        else if (shoppingCartAdapter.currentList.isNotEmpty()) shoppingCartBinding.shoppingCartBtn.root.visibility = View.VISIBLE
    }

}

ListAdapter

@FragmentScoped
class ShoppingCartListAdapter @Inject constructor() : ListAdapter<ProductCacheEntity, ShoppingCartListAdapter.ProductViewHolder>(Companion) {
    private lateinit var clickListener: OnItemClickListener

    companion object: DiffUtil.ItemCallback<ProductCacheEntity>() {
        override fun areItemsTheSame(oldItem: ProductCacheEntity, newItem: ProductCacheEntity): Boolean = oldItem.id == newItem.id
        override fun areContentsTheSame(oldItem: ProductCacheEntity, newItem: ProductCacheEntity): Boolean = oldItem == newItem
    }

    inner class ProductViewHolder(val binding: ShoppingCartListItemBinding): RecyclerView.ViewHolder(binding.root)

    override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ProductViewHolder {
        val layoutInflater = LayoutInflater.from(parent.context)
        val binding = ShoppingCartListItemBinding.inflate(layoutInflater, parent, false)
        return ProductViewHolder(binding).also {
            with(binding) {
                ivProduct.setOnClickListener { clickListener.forwardCardClick(binding.product!!) }
                tvTitle.setOnClickListener { clickListener.forwardCardClick(binding.product!!) }
                btnIncrease.setOnClickListener { clickListener.fordwardBtnIncreaseClick(binding.product!!.id) }
                btnDecrease.setOnClickListener { clickListener.fordwardBtnDecreaseClick(binding.product!!.id) }
                btnDelete.setOnClickListener { clickListener.forwardBtnDeleteClick(binding.product!!.id) }
            }
        }
    }

    override fun onBindViewHolder(holder: ProductViewHolder, position: Int) {
        val currentProduct = getItem(position) ?: return
        holder.binding.product = currentProduct
        holder.binding.btnDecrease.isEnabled = currentProduct.quantity > 1
        holder.binding.executePendingBindings()
    }

    interface OnItemClickListener {
        fun forwardCardClick(productCacheEntity: ProductCacheEntity)
        fun fordwardBtnIncreaseClick(id: Int)
        fun fordwardBtnDecreaseClick(id: Int)
        fun forwardBtnDeleteClick(id: Int)
    }

    fun clickHandler(clickEventHandler: OnItemClickListener) {
        this.clickListener = clickEventHandler
    }
}

Layout

<androidx.recyclerview.widget.RecyclerView
    android:id="@+id/rv_shopping_cart"
    android:layout_width="match_parent"
    android:layout_height="0dp"
    app:layoutManager="androidx.recyclerview.widget.LinearLayoutManager"
    app:layout_constraintBottom_toTopOf="@id/shopping_cart_btn"
    app:layout_constraintEnd_toEndOf="parent"
    app:layout_constraintStart_toStartOf="parent"
    app:layout_constraintTop_toBottomOf="@id/headline"
    app:recyclerview_adapter_stableID="@{adapter}"
    tools:listitem="@layout/shopping_cart_list_item" />

Bindingadapter (app:recyclerview_adapter_stableID)

@BindingAdapter("recyclerview_adapter_stableID")
fun setRecyclerViewAdapterWithStableId(view: RecyclerView, adapter: RecyclerView.Adapter<*>) {
    view.run {
        this.setHasFixedSize(true)
        this.adapter = adapter
    }
}

Solution

  • You are calling ListAdapter.Currentlist.isEmpty() within hideBtnIfListEmpty() too early before making sure that the list is ready and submitted by observeList()

    You can call it after you submit the list to the adapter:

    private fun observeList() {
        shoppingCartViewModel.productList.observe(viewLifecycleOwner) {
            shoppingCartAdapter.submitList(it)
            hideBtnIfListEmpty() 
        }
    }