gab
gab

Reputation: 1

RecyclerView not updating list items fast enough

I have an App that is communicating with a meshNetwork and constantly receiving messages over wifi with the properties of meshNodes. Those nodes should be displayed in a RecyclerView and also updated when a property changes with the usage of LiveData. However when I receive multiple messages at almost the same time, the RecyclerView does not update the list. E.g. a message form a meshNode is received, if the node is not already in a list inside LiveData<List<>> it will be added. After adding it to the list, the bound recycler view displays the node, everything is perfect by now. Immediatly after a new message from another meshNode that is not in the list is received, and added to the list, the meshNode is not displayed in the RecyclerView.

I really dont know why, and every help will be appreciated.

MeshNodeHandler handles messages received from meshNetwork, and updating nodes list

class MeshNodeHandler() : MeshHandler.MeshListener() {
    private val mMeshNodes= mutableListOf<MeshNode>()
    private val mMeshNodesLiveData = MutableLiveData<List<MeshNode>> = MutableLiveData()
    val meshNodes: LiveData<List<MeshNode>>= mMeshNodesLiveData

    override fun onNodeMessageReceived(nodeMessage: NodeMessage) {
        val node =
            mMeshNodes.firstOrNull {
                it.meshID == nodeMessage.meshID
            }

        if (node != null && checkIfNodePropertiesChanged(node, nodeMessage)) {
            Timber.d("Update mesh node")
            // Update node in List...
            mMeshNodesLiveData.postValue(mMeshNodes)
        } else if (node == null) {
            Timber.d("Add mesh node")
            // Add node to list
            mMeshNodesLiveData.postValue(mMeshNodes)
        }
    }
}

MeshNodesListViewModel just exposing the list from the NodeHandler

class MeshNodesListViewModel @Inject constructor(
    private val meshNodeHandler: MeshNodeHandler
) : ViewModel() {
    val meshNodes: LiveData<List<MeshNode>> =  meshNodeHandler.meshNodes
}

And MeshNodesListFragment that observes the LiveData and submits the list to the adapter

class MeshNodesListFragment : BaseFragment<FragmentMeshNodesListBinding, MeshNodesListViewModel>(
    layoutId = R.layout.fragment_mesh_nodes_list
) {
    @Inject
    lateinit var viewAdapter: MeshNodesAdapter

    override fun onInitDataBinding() {
        // DataBinding stuff ...
        viewBinding.meshNodesRecyclerView.apply {
            adapter = viewAdaper
        }
    }

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

        viewModel.meshNodes.observe(viewLifecycleOwner, { 
            Timber.d("Submit list")
            viewAdapter.submitList(it)
        })
    }
}

Logcat:

D/MeshNodeHandler: Add mesh node
D/MeshNodesListFragment: Submit List
...
D/MeshNodehandler: Add mesh node
D/MeshNodesListFragment: Submit List

So the log says that a second node has been added to the LiveData<List<>>, and the list should also be submitted to the Adaper, but there is no second item displayed in the RecyclerView. If I destroy the Fragment and creating it again by switchig to portrait mode, then both items are displayed.

I'm thankful for every reply, cheers and stay healthy!

Upvotes: 0

Views: 503

Answers (1)

Mohit Ajwani
Mohit Ajwani

Reputation: 1338

I think you are missing the notifyDataSetChanged() after you update the list. My understanding is that the list is updated but not reflecting in the view because recyclerView is not updating it's views. Try to call notifyItemInserted() or notifyItemRangeInserted() variants based on if you are adding single or multiple items. Hope this resolves the issue. Let me know if it helps.

Upvotes: 0

Related Questions