I'm having hard time understanding working of view holder, here are my some question that could increase my understanding of viewholder:
It is said that oncreateViewHolder returns viewholder object, What is viewholder object does it contain all the views in single row? if there is list of 1000 item how many viewobjects will be created?
My understanding:
If we are creating viewholder object it contains reference of view like findviewbyid, since findviewbyid is expansive operation, so by viewholder we can create single viewholder object and reuse by just setting image or text(happens in onBindView).
But onCreateViewHolder runs multiple times and as a result findviewbyid will also execute multiple time, isn't performance issue?
Also how its different from convertView of base adapter of simple listview
Thanks!
View holder it is thing which helps u you to reduce find view by id calls.
Let give you an example.
Suppose you have 1k items, each have a 5 view you need to find by id and only 5 full items can be shown once at screen.
So, recyclerView will create 7 (5 + one not-full bottom and one not-full top) view holders. Next time when recyclerView will be scrolled it will use existing viewHolders. Exactly as name says : "RecyclerView"
So findViewById will be called 7*5=35 times.
If you do not use viewHolder you would get 5*1000 = 5000 calls.
35 vs 5000, so you understood I think.
It is said that oncreateViewHolder returns viewholder object, What is
viewholder object does it contain all the views in single row? if
there is list of 1000 item how many viewobjects will be created?
One ViewHolder object for one view row. One ViewHolder object is created for every time the onCreateViewHolder is called. It is called based on the number of visible items in the device. Even if you have 100 items, if ony 10 items are visible, the onCreateViewHolder will be called 10 times and there will be 10 ViewHolders. (There might be one or two extra item based on the RecyclerView optimizations because if you scroll the list, the next item should be visible instantaneously)
My understanding: If we are creating viewholder object it contains
reference of view like findviewbyid, since findviewbyid is expansive
operation, so by viewholder we can create single viewholder object and
reuse by just setting image or text(happens in onBindView).
RecyclerView is already recycling and reusing the Views and the corresponding ViewHolders. The number of ViewHolder (and View) present at any time depends on the number visible items on the screen.
But onCreateViewHolder runs multiple times and as a result
findviewbyid will also execute multiple time, isn't performance issue?
As said previously, the number of times this will be called is only for the number of visible items. When you scroll, the views and viewholders are reused. You have distinct Views for each row. So there will be distinct ViewHolder for each row.
Also how its different from convertView of base adapter of simple
listview
In ListView, the convertView is the old view, which provides an option to reuse the same view for new rows as you scroll the list. But it's optional because the developer might not use the convertView at all. In RecyclerView the reusing of old views is done automatically.
RecyclerView.ViewHolder is a helper class that holds the View of a row or rows.
One or more ViewHolder is created for each viewType.
if several rows have the same ViewType then the same View can be reused for several rows.
Overriding getItemViewType(int position) is the way to have several view types. If getItemViewType returns a not used before viewType then onCreateViewHolder will be called to create a new ViewHolder.
Adapter onBindViewHolder is the place to fill the view with specific data for each row.
ADDED:
A concept must be clear: what makes a ViewHolder to be reused is that it shares the same viewType.
Instead if you make getItemViewType(int position) return a different value for each row then each row will have its independent ViewHolder and view.
assume that you want to show a list of 1000 items and there are just 10 items visible to the user in the screen. your adapter creates 10 ViewHolder instances to show them at the same time. when user scrolls and the adapter has to show more items, instead of creating new instances of ViewHolder, it reuses items that are not visible anymore. your adapter prevents creating new Views and saves CPU time by doing so.
Related
How Recycler view Bind Data One By One or All in one time?
void onBindViewHolder (VH holder,int position,List<Object> payloads)
Called by RecyclerView to display the data at the specified position.
This method should update the contents of the itemView to reflect the
item at the given position.
So one by one. More here .
Your recycler view calls RecyclerView.Adapter when you set adapter to recycler view or
notify dataset changes to the adapter.
Recycler view calls OnBindViewHolder for each item in your recycler.
Hence, recyclerview binds data one by one.
You can clearly see this when you implement animation to the recycler view items.
RecyclerView is a list drawing library that essentially provides a fixed-size window to load a large dataset into. It recycles the views it created at the begining when the views go out of scope (window) and then if there is a need, reuses them to make it seem as if the views were never offloaded and were virtually present outside the window.It binds the rows which are visible to you and recycles the rest
how to update ReyclerView adapter without make OnCreateViewHolder(...) being called?
Because when i do
mRecyclerView.getAdapter().notifiItemChanged(position)
it goes inside OnCreateViewHolder(...) what i don't want to. The reason why i don't want is because I have expanded item view and onCreateViewHolder(...) will reinflate it so make collapsed. I only want to OnBindViewHolder(...) being called
Have anyone faced with it?
UPD:
Just found that OnCreateViewHolder(...) is called only one first time, in all next times it's not being called. What is the reason?
t
You could add a boolean isExpanded to your data objects in your dataset, and then in the onBindViewHolder method check whether isExpanded is true, if so expand the view programmatically. (and ofcourse don't forget to switch the boolean when expanding/collapsing the view)
This is the whole point of RecyclerView : it handle a pool of view holders, which are created once (calling OnCreateViewHolder()) then reused (or recycled, hence the view name) as much as possible via OnBindViewHolder().
OnCreateViewHolder() is used to create the views, while OnBindViewHolder (re)set the views state (like text content, selected state, ...)
It follows that any state associated with an item (like the expanded / collapsed state) should not be stored in the ViewHolder. You can for example use a private List in the adapter.
Normally in ListView are used in android,but how many items can totally load in list view ? Is it possible to load more than 10,000 items ?
ListView itself will keep only a handful of view items in memory - those that are displayed on screen and possibly a few scrap items that are waiting to get recycled. ListView is not the limiting factor.
What is a limiting factor is the Adapter that feeds the ListView. If your adapter implementation keeps all data items in memory (e.g. an ArrayAdapter), then you're bound to hit a limit at some point. There are other adapters such as CursorAdapters that load the data items on demand and don't keep everything in memory. They scale further.
Of course there's usability. ListView is practically unusable for browsing through a list of 10000 items. If you really have that much data to display, you have an user interface design problem.
Try to use ViewHolder and convertView in View getView(int position, View convertView, ViewGroup parent). You can load more than 10,000 items with low memory usage.
I am doing a BaseAdapter sub class for a custom ListView.
I would like to know what the parameter, ViewGroup parent does?
Does it refer to the list view or the parent of the XML file to be inflated ?
public View getView(int position, View convertView, ViewGroup parent)
Thank you
ViewGroup is a parent of your View.
Explanation :
When you make an xml layout you put your view into some layout(Relative,Linear etc.) That is a parent of your view. And when android call getView method he need know, what the parent of your attached View.
getView method must return a View list item . To do this, we create layout- resource R.layout.*.xml. In this method, we must of R.layout.*.xml create a View, fill it out and send data list . But before you create, we try to use convertView, which goes to the input method. It has previously created View, but unused at the moment. For example, when you scroll through the list of the items out for the screen and no longer draws the need . View of the "invisible" items used for new items . We can only fill them with data . This significantly speeds up the application , as do not need to chase inflate once again .
If convertView this time we were not given (null), then we create view.
ViewGroup is a parent of our View, that means our xml view. getView method basically for to working with our view which you would like to show in a one row. So obviously it consists your layout's parent view.
getView() method returns a view for each item (each row of ListVew)within the adapter view. The layout format and the corresponding data for an item within the adapter view is set in the getView() method.It will be a performance nightmare if getView() returns a new View every time it is called that's where the concept of Adapter came into feature.However, ListView recycles the views that are not shown any more, and gives them back through convertView.
To understand how Adapter works, you can refer the following,
http://www.edureka.in/blog/what-are-adapters-in-android/
http://www.piwai.info/android-adapter-good-practices/
I need to add a switch (Android 4.0+) to my ListView , just a single switch with an ImageView Button , I have seen soo many tutorials that teach of adding several views in the list activities but what I need is just a single option of the list to have this switch . I know if I can put a button or textView I can put a switch in there , but I can't understand how is putting a button or any view there without repeating the whole same scenario on all the options , as for me , I am new to the ArrayAdapters and ListViews , but I need to learn these two so I can use them later on ! what I need is like this for example:
______________________
Image | Switch
______________________
Normal option
______________________
Button | Whatever view
_______________________
Normal option
_______________________
Checkable Option
_______________________
and so on ... So if you clearly , I want full control over every single option in there , thats what I need and want . Thanks for any help :)
if you're gonna do it by listview, then you can do it by being explicit about each position in the getView method of the adapter. here's an example:
public View getView(int position, View convertView, ViewGroup parent) {
switch (position) {
case 0:
// do image switch option
// convertView = layout 0
break;
case 3:
// do button whatever option
// convertView = layout 3
break;
case 5:
// do button whatever option
// convertView = layout 5
break;
default:
// do normal option
// convertView = layout 1
break;
}
return convertView;
}
getView is a method in many android adapters that returns a view. When hooked up to a listView, it will be recognized as the method to return a view for each one of its rows. Each row in a listview that you see is the product of one executed instance of this method. You don't call it: it is called automatically whenever rows of a listview need to appear, or whenever a row position moves off-screen and comes back, or whenever the listView is being refreshed, in general whenever listview rows must be "made". It is there for you to override so that you can customize how ever for the specific look that you want.
convertView is a view as well. It is the product of a concurrent mechanism running in the listview adapter called view-recycling. Imagine that you have a listview that needs to display 1000 rows for your game's shopping menu. a conventional approach would be that you simply make an inflate command for your in getView for a vibrant xml and edit the components to show the item differences. So, that's inflating a 1000 times (and inflating is a expensive step, mind you), plus all that has to be in memory and is just clogging up your garbage collector. Plus, what if you need to refresh something to show changes? Get outta here! There are quad-core phones now, but there is a better way.
listviews done right don't actually make 1000 views at once but only the 7 or 8 that are on the screen at a time. When a listview row view is scrolled beyond the boundaries of the phone's screen, it isn't thrown out just yet. This concurrent mechanism runs and this view is saved and held under the title of convertView and passed in as a parameter for the next getView call. Not to (re-)use it is a terrible waste, because essentially you have a view that looks like the next row in the next getView call, perhaps with only the text in a textview changed or something like that, but you're gonna do another expensive inflation anyway. Then the unused convertView knows that it's second chance has been disregarded, into the GC, and it's business as usual.
The above code doesn't make use of convertView, because frankly it wasn't asked in the question, but it's very simple to utilize.
public View getView(int position, View convertView, ViewGroup parent) {
if (convertView == null) {
// inflation step
// convertView = inflation
}
// rest of code involving components of inflated view
return convertView;
}
First you check if there's nothing there, which you can imagine is when a listview is first launched and nothing has had the chance to be on deck to be thrown out. And only then do your inflation then. Next time around, getView will have it's mouth full with used view and will plug it in (if it's being returned). This is the single most beneficial action for your listview performance-wise that you can do right off the bat.
But you should know this, about half the questions tagged android on this site are on this alone, there are no guarantees that convertView will plop in the position that you want, as in right below if you're scrolling up and right above if scrolling down. Just make sure that you're being explicit about what goes at what position and you'll be fine. For more information on this and other listview know-how watch this: http://www.youtube.com/watch?v=wDBM6wVEO70.