I am using recycler view(https://github.com/thoughtbot/expandable-recycler-view) to display list of sections and subsections. It is working just fine. But when I am trying to update the list with live data and using :- recyclerView.adapter = adapter by creating adapter everytime when live data updates. But when data is updated, it collapses the each section regardless it was expanded already. I want to keep state of list as it was when updating it. Can someone tell me how to achieve this or any other way of updating the adapter that keep the state of list same(if it is expanded, remain expanded, collapsed, remain same). Thanks in advance.
Related
What's my Goal?
I need to update a nested Recycler View and all it's content, if a Switch changes it state (isChecked true/false) AND any other Item within the RecyclerView has the Same Category, then Update each of the Item's with the same Category to Disable the Switch. I need to disable the Switch Button, to prevent the User from selecting more than 1 Item of the same Category.
What's the issue?
My nested Recycler View will update my RecyclerView correctly, if the RecyclerView get's initially loaded, displayed and if I don't scroll even a nano-centimeter. But if I scroll the RecyclerView, nothing will update anymore... sometimes it does update the WRONG RecyclerView and only 1 Item... so no matter what Category I switch the (isChecked) to 'true', it will update 1 Item in a different RecyclerView (Everytime the same Item, which I checked before I started scrolling)
How is it implemented so far?
I have a RecyclerView which has an TextView on Top and a nested RecyclerView beneath it. This Nested RecyclerView has an Item, which basically consists of an Id, CategoryType, Text and CreationDate.
I'm using DiffUtil to do all the hassle for me (notifyDataSetChanged, notifyItemInserted... etc).
val diffUtil = CategoryDiffUtil(_categoriesWithinRecyclerViewAdapter, inNewCategories)
val diffResult = DiffUtil.calculateDiff(diffUtil)
diffResult.dispatchUpdatesTo(this)
I'm sending a new List of Categories to the "setData" functionallity within the FirstLevel RecyclerView, which calls each Nested RecyclerView's "setData" functionallity with the Categories for the Day. To know, which Item's Switch needs to be disabled, I store the Selected Category-Type in a List within the Nested RecyclerView where I recently Checked (Switch.isChecked == true) a Category. Every FirstLevel RecyclerView has an List of Reference to Adapters of the Nested RecyclerView beneath him. This is how I'm able to call "setData" or generally update the Nested RecyclerView (See Code for adding Adapter to FirstLevel RecyclerView to update beneath Nested RecyclerViews later)
if(_adapters.isEmpty() || !_adapters.any { it.first.contentEquals(inNewCategories.getCreationDate()) }){
_adapters.add(Pair(inNewCategories.getCreationDate(), _adapter!!))
}else if(_adapters.any { it.first.contentEquals(inNewCategories.getCreationDate()) }){
_adapters.removeIf { adapter -> adapter.first.contentEquals(inNewCategories.getCreationDate()) }
_adapters.add(Pair(inNewCategories.getCreationDate(), _adapter!!))
}
What have I tried to fix my Issue?
Tried to use nestedRecyclerViewAdapter.notifyDataSetChanged(), but it didn't help (does have the same issue mentioned in "What's the issue?").
Added Logs to ensure, that the Nested RecylcerView Adapter's are correctly stored and replaced. Ensure that the DiffUtil get's triggered if something changed (It does, and it know's exactly which item's needs to be updated)
I Tried to use Compose LazyColumn + StickyHeader to see if this changes something. But I'm still to inexperienced with it, that's why it was running far slower than my Nested RecyclerView and I gave up (for now) on using it (compose).
Not sure if I explained any crucial detail, but I hope someone could help me.
I have a recycler view with a delete button for every item,and the data for the recycler view is a Live Data list.
Basically im observing the list and when i delete an item i just pass the adapter again to the recycler view with the new list in order for the list to update,like this
viewModel.loadBasketItems().observe(viewLifecycleOwner, {
adapter = BasketFragmentAdapter(it, viewModel, requireContext())
recycler.adapter = adapter
})
My first problem with this is that the image jumps to the top of the list every time i delete an item,because the list is created again completely
My second problem with this is i don't think this is very efficient.
What's the best method to update the recycler view after you change something
You shouldn't be resetting the adaptor like that. Keep the adaptor the same, but call notifyDataSetChanged(). This tells the adaptor its data has changed, which will tell the recycler view to redraw itself. What you're doing makes the recycler view assume it has a whole new adaptor and needs to drop all info about the old one.
Even better would be to call one of the more specific notify functions on the adapter that tell it what elements changed, but the general one is good enough until you see perf issues.
I have a ListView which I populate using a custom CursorAdapter.
Now I want to manually update just one specific item in the ListView. I have the content URI of that item. Is it possible to use just this info to get the position of the item in the listView?
If I have the position I can do something like
View v = mListView.getChildAt(itemPosition - mListView.getFirstVisiblePosition());
to update the view. But how can I get itemPosition?
I know that I get the position in the onItemClickListener, but I need to update the view without it being clicked.
Any help guys?
ListView does not support updating a single position.
You must update the adapter with the new data (even if you change a single position) and the, invoke mAdapter.notifyDataSetChanged()
If you get the View by its position (via listView.getChildAt()) will work. However, if you scroll up and down the list, that view will display the old data again because the adapter is not aware of the change (and it is the adapter which update the view contect view getView()).
When you invoke notifyDataSetChanged(), you are telling to the adapter that your data set has new info and the ListView/Adapter will re-draw the visible items (it won't re-draw whole list at once.. only the visible items).
You may want to consider to change to RecyclerView in the future. The BaseAdapter used in a RecyclerView support actions such as add/remove/update a single position.
I am using Firestore Paging Adapter for loading a list of data and displaying it in RecyclerView. I set onClickListener on each item loaded and I would like to remove item from RecyclerView if it is pressed. How can I do that.
I get pressed item with
val pressedUserRealtion = getItem(adapterPosition)?.toObject(UserRelation::class.java)
and I would like to delete this item from my RecyclerView. I searched and couldn't find any method that would do that, I can't get the reference to list that contains loaded items. The only thing I can think of is setting the view visibility to GONE when user selects the item.
for realtime update, you can use FirestoreRecyclerAdapter
FirestoreRecyclerAdapter — binds a Query to a RecyclerView and
responds to all real-time events included items being added, removed,
moved, or changed. Best used with small result sets since all results
are loaded at once
Documentation
I'm using RecyclerView with expandable list items. The problem is that when I expand an item and scroll the items off-screen gets reset like this:
Is there any way to fix this and preserve the item's state?
Thanks in advance.
You need the object in your ListAdapter to store the expansion state. It may be that you need to create a new class that wraps the existing data and adds a boolean indicating if the row is expanded. Then, when you re-initialize the view as the list is scrolled, you can set the view to be expanded or collapsed according to the data in the adapter. The view itself can't hold this state for you because the view object is "recycled" to display a different record as the user scrolls.