This is not code Question.
As I saw on some website, RecyclerView's setAdapter should be run only once the first time.
What is the reason?
If so, in the Nested RecyclerView, the person of this video keeps calling the
setAdapter() of the Sub RecyclerView every time it is recycled in
onBindViewHolder(), is it wrong??
https://www.youtube.com/watch?v=EyUjw6b5gXE
ADDED
No he is right I think. Let see the logic which was proposed in the video. You have parent list with child items. It is ordinary situation as I know. But every child item in parent list is parent item for its list which is stored inside the child item of the parent list. So when you call setAdapter() inside container of parent list you send data to its children and their children And what about onBindViewHolder(), why setAdapter is called every time? It is very simple, let see into documentation:
RecyclerView calls this method to associate a ViewHolder with data.
The method fetches the appropriate data and uses the data to fill in
the view holder's layout. For example, if the RecyclerView displays a
list of names, the method might find the appropriate name in the list
and fill in the view holder's TextView widget.
So when you send data for the first level RV you associate child RV with some data for which purpose you call setAdapter in each item of parent list. So it will be called in every position of the parent list item to assign data to the child list which also will have some data holders with its handling. Let see life example:
grandfather (activity) bought some candies for his children (first level list items) who will give some of them to their children (second level lists which are items of first level list items)
and for passing some candies between among relatives we use setAdapter() method :) I hope I explained your question and you will understand this video :D
Related
I have a nested recycler view that contains parent and child adapters. I am using Room DB for showing data on the recycler view.
When I, add or delete data from a parent or child list item or parent list item, it goes to the first position.
This is how I, collect data from the view model
This is how I, collect data from Room DB and emit for activity
These are some edit delete operations executing in the activity
I just want when I, execute any operation the position remains the same not scroll for the first position. There is also a solution called the smooth Scroll To Position method but I want a solution without using this function.
In your collect lambda, you are setting the recyclerView's adapter every time a new flow is collected, which is making your recyclerView go on the top.
You should move binding!!.parentRecyclerView.adapter = adapter to either onCreate if using inside an activity or onViewCreated if fragment.
You can also do a null check and set only if the recycler views adapter is null. This should be avoided as it is more idiomatic to set it when the view gets created.
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.
Kindly help me out for this situation.
I'm having recyclerview and on view click I used your library for expand and collapse. Issue here is expandableview layout has been created dynamically based on the API response. So on the time of API loading if I scroll the layout then the view not updated with the records from API.
I'm calling the API only on click of recyclerview item row and fetching the API and constructing the layout.
onBindViewHolder will get called on scroll and view got refreshed. But I'm not sure how to load childview data when scrolled.
I inserted "notifyItemChanged" in OnBindHolder but it throws exception layout can be refreshed on scroll Illegal state exception. Kindly share your thoughts.
Library which I used inside RecyclerView view for expand/collapse - https://github.com/cachapa/ExpandableLayout
Thank you
Cause for the above issue:
Calling API on click of child view and store the response in model.
Make the child view model getter/setter in Parent view itself which will be easy to reload the view.
Don't get the holder reference in API Success call method and set the values for child view. When API getting called in background if we scroll then view holder reference will get changed. Which makes particular row values not updated on scroll.
Solution would be:
Create Parent model with child model values too as getter/setter refrence.
Then now as-usual create your view adapter which parent model values
On Child View click fetch API response and store in model and call notifydatasetchanged function.
Then in your onBindViewHolder method make a condition if(Selpos == clickedposition) then call your dynamic view method which updates the values from model.
I have a listview with 4 identical rows. Inside those rows, I have a RelativeLayout which contains a TextView (id : R.id.notif). In my Activity, I use my own ArrayAdapter.
I would like to be able to modify the text of the third row. I tried this but it isn't working.
((TextView)listview.getAdapter().getView(2, null, listview).findViewById(R.id.notif)).setText("50");
Thank you.
Do not use adapter.getView() for that! This method is used internally for the adapter to create the view that gets displayed in the list! The correct way to do this is to modify the underlying data and to refresh the list with adapter.notifyDataSetChanged(). Do not try to access views in the list directly, you don't know if they are visible at the moment or scrolled outside the view.
I have a ListView with custom_row , every row has a textView1 and a textView2 , the list has now 2 records , and i have a button that is not on the list.
When i click the button i want to get the text from textView2 of the 2 records.
Is it possible?
I would take a shortcut, you ListView is being populated by an Adapter that uses a dataset. This dataset can be almost any datastructure such as Array, ArrayList, etc.
The layout you define, such as custom_row in you case only defines the structure of your view i.e. "where" items will show within on item on the list.
On the other hand, it is still your responsibility to tell the ListView "what" to show within the textView1 and textView2. You do this using the Adapter which connects the ListView to the dataset. More often than not, the ListView is a one-to-one mapping of the dataset i.e. the first item on the list is the first item in you dataset (I don't know what you are using for only two items, might be an array).
The ListView calls getCount() on the Adapter to find out how many total views there will be. It then call getView() for each view to be shown on the screen. It is in this method that you define what will actually show in a single view on the list (your custom_row).
Now you would know which entry of the dataset is supposed to populate which view in the ListView so you can just read it off there. For example, if your getView() does:
textView2.setText(getItem(position).getSomeTextField());
And the original dataset is an ArrayList named listDataSet
You could just do listDataSet.get(2).getSomeTextField()
NOTE: You will have to manage the scope of the dataset so that it's visible from wherever you are calling.
Get back your ListView (maybe already stored in an object thanks to findViewById, or by calling getListView() on your ListActivity).
Then call getItemAtPosition() on your list view, with the position you want.