RecyclerView adapter inside a fragment is not updating when data changes

Viewed 106

I have an activity that contains 2 tabs and each tab has a fragment inside ViewPager. Each fragment have a RecyclerView. When I navigate to another activity the data inside the Fragments should be updated. Although the data is being sent correctly to the fragment, the original data is displayed. I tried using notifyDataSetChanged() method inside the fragment but it didn't work. I also tried calling it from the activity like:

if (!pickedItemsList.isNullOrEmpty() && notScannedItemsFragment != null && notScannedItemsFragment.isAdded)
{
    notScannedItemsFragment.notScannedItemsAdapter.notifyDataSetChanged()
}

However, it didn't work too.

That's how I am initiating the fragment:

override fun initFragments(savedInstanceState: Bundle?, pickedItemsList: ArrayList<OrderDetail>, remainigItemsList: ArrayList<OrderDetail>) {
    val listener: ItemsInteractionListener = object : ItemsInteractionListener {
        override fun onSwipeToRefresh() {
            presenter.onSwipeToRefresh()
        }
    }

    if (!pickedItemsList.isNullOrEmpty() && notScannedItemsFragment != null && notScannedItemsFragment.isAdded) {
        notScannedItemsFragment.notScannedItemsAdapter.notifyDataSetChanged()
        scannedItemsFragment = ScannedItemsFragment().newInstance(remainingItemsList)
        notScannedItemsFragment = NotScannedItemsFragment().newInstance(pickedItemsList)!!
    } else {
         scannedItemsFragment = ScannedItemsFragment().newInstance(arrayListOf())
         notScannedItemsFragment = NotScannedItemsFragment().newInstance(allItemsList)!!
    }
    scannedItemsFragment.setListener(listener)
    notScannedItemsFragment.setListener(listener)
}

allItemList is the original list and pickedItemsList and remainingItemsList are the lists after the changes (that I got from the other activity)

This is one of the fragments classes:

class NotScannedItemsFragment : BaseFragment() {

    private var listener: ItemsInteractionListener? = null
    lateinit var notScannedItemsAdapter: OrderItemListingAdapter
    private var itemRemainingCount: Int = 0
    lateinit var notScannedItems: ArrayList<OrderDetail>

    lateinit var recyclerView: RecyclerView

    lateinit var fragmentView: View

    fun newInstance(notScannedItems: ArrayList<OrderDetail>): NotScannedItemsFragment? {
        val notScannedItemsFragment = NotScannedItemsFragment()
        val args = Bundle()
        val order = Gson().toJson(notScannedItems)

        args.putString(IntentConstants.EXTRA_NOT_SCANNED_ITEM_LIST, order)
        notScannedItemsFragment.setArguments(args)

        return notScannedItemsFragment
    }

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        val str = arguments?.getString(IntentConstants.EXTRA_NOT_SCANNED_ITEM_LIST)
        notScannedItems = Gson().fromJson(
            str,
            object : TypeToken<List<OrderDetail?>?>() {}.type
        ) as ArrayList<OrderDetail>
    }

    override fun onCreateView(
        inflater: LayoutInflater, container: ViewGroup?,
        savedInstanceState: Bundle?
    ): View? {
        fragmentView = inflater.inflate(R.layout.fragment_not_scanned_items, container, false)
        recyclerView = fragmentView.notScannedItemListing
        return fragmentView
    }

    fun setListener(listener: ItemsInteractionListener) {
        this.listener = listener
    }

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

    override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
        super.onActivityResult(requestCode, resultCode, data)
    }

    private fun setUpRecycler(view: View) {
        imageLoader = ImageLoader(context)

        notScannedItemsAdapter = OrderItemListingAdapter(
            false,
            imageLoader,
            object : ImageClickListener {
                override fun onImageClick(
                    itemName: String,
                    itemQuantity: Int,
                    url: String,
                    barcodes: List<String>?
                ) {
                    startImageFullViewActivity(itemName, itemQuantity, url, barcodes)
                }
            })

        notScannedItemsAdapter.addItem(notScannedItems)

        notScannedItemsAdapter.notifyDataSetChanged()

        view.notScannedItemListing.apply {
            view.notScannedItemListing.layoutManager = LinearLayoutManager(context)
            view.notScannedItemListing.setHasFixedSize(true)
            view.notScannedItemListing.isNestedScrollingEnabled = false
            adapter = notScannedItemsAdapter
        }

        notScannedItemsAdapter.printList()
    }

    fun showOrderItemListing(notScannedItems: ArrayList<OrderDetail>) {
        this.notScannedItems = notScannedItems
        itemRemainingCount = notScannedItems.size


    }

    fun getItemsRemainingCount(): Int{
        return notScannedItems.size
    }

    fun clearItems() {
        notScannedItemsAdapter.clearItems()
    }

    fun updateAdapterContent(pickedItemsList: ArrayList<OrderDetail>) {
        if(this::notScannedItemsAdapter.isInitialized ) {
            notScannedItemsAdapter.clearItems()
            notScannedItemsAdapter.addItem(notScannedItems)
            notScannedItemsAdapter.notifyDataSetChanged()

        }
    }
}
1 Answers

It turns out since I'm getting the list from arguments it's not updating with the new list. As stated here: Anything initialized in onCreate() is preserved if the Fragment is paused and resumed.

So I added a boolean variable loadListFromArgs and I only loaded the list from args if it's true and when I call updateAdapterContent I set it to false.

Related