So I am having a problem with the different pieces of that make up my ListView. I put them into an ArrayList and use a custom ArrayAdapter to hook up to the ListView, which I have done before so I don't believe there is a problem there. Initially the list seems to have the pieces in the correct order, but then I will scroll down the list and the contents will then load in incorrect order. I then scroll back up and everything is jumbled. Has anyone run into this before?
Thanks
-Jake
Yes your problem is related to the fact that List reuses the views for each row. So say your list can see 5 items, but your ListAdapter has 15 things in it. Android will create 5 + 1 instances of your row view instead of 15. One for each row in the list + 1 for when half of the top and bottom can be seen. When a row is moved out of the visible area the List will recycle that view instance for another row instead of creating a new one. If you don't properly reset all of the user interface components every time you'll get artifacts from other rows showing up. You must make sure that every time you bind your data from the objects in your array list to the view you set every field every time.
For a better description of this see
http://www.youtube.com/watch?v=N6YdwzAvwOA&feature=related
Related
I have a simple listView with simple adapter and I am getting a new live content (it means data with changed items) every 5 sec. I have to update some rows with new values, so I clear adapter and addAll in list, but then all list is freezing and scrolling up.
If it's a short list, all is work good, the problem becomes when I have long list with scroll.
Is there better solution for my task? How could I monitor only changed rows and redraw there?
Instead of ListView use RecyclerView. RecyclerView allows to refresh and add individual elements to list.
Adapter method item added at position
So my solution is. As I have abnormal list (I'm getting response from back-end with different values for each row, I must to group it and generate unique layout for each row), so I've used a TableLayout, I generated each row and put it to Map, when I catch new response I check old value with new one and if there are different, I take View from Map and bind new data.
In most case, we need to implement the BaseAdapter’s getItemViewType() and getViewTypeCount() for dynamic item content of the listview, as this post says. But I think this solution is only suitable for finite number and knowing beforehand, such as listview item with sending layout and receving layout.
What about the case that the listview with its item content impossible knowing beforehand?
For example, I need to show a contact list from server, the contact list size is about several thousand. For each item, I need to show, for example, the hobby “list”. It is a small range of 0 to tens of string. So in this case:
The item types is relatively bigger than normal case using “getItemViewType”
Though each item may be different, but similar to a certain degree: the item content is different in the number of views, but common in view type. Item A is different from item B only because it have more TextViews.
For each time in the getView, the convertview is hard to simply reuse because they are different, but if we create new TextView and added to the convertView, it will impact the scrolling of the listview. I don't think it's appropriate such way. What should i do in such case?
Unfortunately you cannot easily change the number of item view types on the fly. The getViewTypeCount() method is only invoked when the adapter is set on the ListView. That means, were you to dynamically change it, then you would have to call setAdapter() again. This is a huge performance hit as the ListView will toss out all the recycled views and re-generate everything from scratch again.
Honestly, it looks like you should be using an ExpandableListView instead. It allows you to displays lists of items under groups. The only difference is the groups are placed on top of the list. So where you have A, B, C, D on the left side in your picture...in the ExpandableListView it'll sit on top.
The ExpandableListView can easily handle your situation where a given grouping could have any variable number of items within it. You mentioned needing to store a contact list. I'd suggest taking a look at a RolodexArrayAdapter for use with the ExpandableListView. It may be of help.
Based on the question How can I update a single row in a ListView? I want to update all the visible rows beside the one that I'm changing in the moment. I can take any row that I want with listView.getChildAt(index) but I don't know how can I compare the the returned view with another view that I already have. Their Ids are based on the view definition in the XML file so All the rows have the same Id.
Any help is welcome, thanks in advance.
That question was for a very specific case. If you want to update all rows, then
Only the rows "visually on the screen now" are actual children views of the ListView. It wouldn't even make sense to want to update the others.
Doing it individually for each child view would be, in fact, a very roundabout way of refreshing the whole ListView.
Just change the Adapter's backing data and then call notifyDataSetChanged() on it. It will refresh all visible items (calling getView() for each one), and as you scroll the new ones will be shown as updated too.
My problem is similar to ListView getChildAt returning null for visible children, but despite searching I cannot find a solution.
I have a ListView with a Scroll. The ListView has 10 items, 7 of which are visible and 3 are hidden by scroll. I also have an external method (out of adapter) that must get all of the children from this ListView (e.g. using getChildAt()).
I need all 10 of the items, but the last 3 are null objects. I've tried code like the following:
getListView().smoothScrollToPosition();
But this doesn't work.
I think that I don't need to post the rest of my code, as the description says everything?
As you have already seen you can't get all the child row views from a ListView simply because a ListView holds only the views for the visible rows(plus some recycled rows but you can't reach those). The correct way to do what you want is to store whatever data in the adapter's data and retrieve it from there.
But the ListView doesn't keep the current values from RadioGroup in
running time.
I've seen that you have some problems with this so I've adapted some old code to build a basic example, code that you can find here.
I don't think so you need to add scroll view for a listView. Scroll automatically works on ListView. Try your application without adding scroll view and I'm sure it'll work as you needed.
The reason those children are null it's because they really do not exist and they will never exist, if only 7 children are on the screen at one time, the system will only create 7 and re-use by passing the convertView back to the adapter getView() method.
If you want to grab information regarding your whole dataset you should search on the dataset itself, instead of the views on the screen. E.g. if it's an ArrayAdapter, loop the array; if it's a CursorAdapter, loop the cursor; etc.
The non-visible children of a listView don't actually exist. When they become visible, one of the redundant views is recycled or a new view is generated. So you can't actually access all the views. Why do you want to? Whatever changes you want to make should be made to the data that populates the views rather than the views themselves.
There are a few point that you need to take care of:
1. List view provides inbuilt scroll functionality, So don't use Scroll view. It will only mess up things.
2. List view doesn't contain ALL the children. When you scroll it, it creates only visible items on run time.
3. If you want to get all the children altogether, Better keep an ArrayList of the child objects that your list has. You can add or remove children to this ArrayList as per requirement.
I have a listview with radio button. when i click any option and scroll that list view the previous select will cleared.How to do this. The actual problem is when scroll the view on every scorll the view is refreshed, that's why every time the view is refreshed. How to do this I can't get any solution, Plz. Help.
Check your adapter, you are probably don't do the job right on bindView. You have to set again on bindView the values.
I will reformulate the sentence and you will probably will understand.
The newView creates only 5-10 views (as many they fit on the screen), and they are reused for other rows. If you have a ListView with 200 lines in it, actually you have only 5-10 views, and you have to make sure you update the views with the valid changes in bindView. You have to store/save the changes to an object for later reuse.