When I check my logs, when using ListView, I see, that getView() method of a custom adapter is continuously invoked on first 6 elements, even if I scroll to the very end of the list. Has anyone seen behaviour like this?
Well, the answer has been accidentally found here.
Just never, ever set ListView's dimensions to be "wrap_content".
Related
In my Android App, I have a ListView which contains several elements. For certain user inputs (touch events), it happens that one element in the ListView calls invalidate() on itself. The problem is that sometimes, the element then redraws itself and sometimes not. When it does not redraw itself after invalidate() has been called, I need to scroll the ListView in order to get the desired redraw. Of course, I don't want that.
It is to mention that I never call listview.invalidate() but only element.invalidate(). Has anyone an idea on how to fix this?
As we all get older, we get wiser. My problem was that I did not use convertView in the Adapter's getView method but kept all the views in an ArrayList. Bad practice, ladies and gents. Use convertView and everything will work buttery smooth.
I'm having some difficult time figuring out when the ListView decides to recycle all it's views. I have 2 different ListViews where i change some layout stuff and play an animation after that. In my first ListView this works fine, only the row i'm trying to change is actually being affected, yet in my other ListView all rows are affected and the Views are being reused.
I can't really post any code, as there are quite a few classes involved in this. I tried to break it down and noticed it reuses the rows after calling requestLayout() at one of the descendant views of the row. But in my other ListView i do the same and it's not called at all.
Nowhere in my code notifiyDatasetChanged() is called either, nor am i changing any other views.
I just trying to find out when ListView actually needs to reuse the views.
ps. I'm using 2.3.3. And i'm aware of setHasTransientState() in 4.1. But i can't use that unfortunately
I found my specific problem.
After long debugging through the source of the ListView I found the difference in behavior between my two ListView implementations. I found out that one of them was calling onSizeChanged(), first to a new height immediately followed by another onSizeChanged() with the old height. In this method it sets a flag mDataChanged which in turn will cause the views to be recycled.
In my other ListView i have fixed row heights so it never has this problem. I'm going to do the same for this situation as i don't really need different row heights.
I have a ListView with custom Adapter. To be honest, I have many of them at the same time on screen, and my Tegra 3 device started to lag, what made me really confused... I found than in each ListView's Adapter the getView() method is called for all visible rows every time any animations runs on screen. That gives me like few hundreds of calls per second! Digging more, most of these calls are due to measure() and onMeasure() calls of ListViews' parents, and - this is tke key - they are useless, because all the layouts of my ListViews
have const size.
So my question is: how to eliminate these calls? Of course I want to leave proper calls alone (caused by adding items to Adapter and notifyDataSetChanged() ).
I've tried almost anything, but either the whole list doesn't draw itself (when I overriden it's onMeasure() and forced to returned const size without calling super.onMeasure()) or stops updating at some time.
How you implemented the getView() method? If you implement it in the correct way there should be nearly no lagging.
Check out this really really good video:
http://www.youtube.com/watch?v=wDBM6wVEO70
Slides: http://dl.google.com/googleio/2010/android-world-of-listview-android.pdf
As Romain said, work with it not against it. Best is to leave measure() alone and focus on your adapter.
Thats how ListView is implemented.. I don't think that will cause a performance Overhead.. Provided you do things properly there..
For example..
Don't instanciate LayoutInflator inside GetView Method, Do it at class level..
And Inflate View Only if the convertView==null or else just return convertView.. Inflating view is a costly process....
Well like you said these calls are due to measure() and onMeasure() calls of ListViews parents and I'm sure you are using height=wrap_content also with wrap_content on height your ListView will check without stop if your height has changed.
So the solution is to put the height=fill_parent.
I hope this helped you.
The underlying reason for this is that ListView.onMeasure() calls AbsListView.obtainView(), which will request a view from your list adapter. So if your view is being remeasured through animations, your performance will be very poor.
I have a ListView which gets items from a db (using SimpleCursorAdapter). After the list is populated I want to scroll it to a given position. I can't find the right place to do this.
Right now I set a "need to scroll" flag before running the query. Then I check this flag in setViewValue() and if it's set I scroll the list and reset the flag. Although this works, I don't think it's the best way to do it.
Any other ideas about how to perform some actions when a ListView is populated?
Perhaps you're looking for a "scroll-to" like method. Here's a quick reference.
Ok, I think I solved this. Derived my own adapter from SimpleCursorAdapter, overloaded notifyDataSetChanged method so that it scrolls the list when necessary after calling super's method. Looks working.
I am trying to get a button to show up on my list item (declared as android:visibility:"gone" in the XML) to show as visible when I perform some gestures on it. However, how can I actually notify the getView method correctly to display the button only on the listview item?
I tried using getChildAt(position) which ended up displaying several buttons at once.
I tried passing in the position for example I detected that the gesture was performed on from pointToPosition and passed it into the adapter for the getView method to display, but it had the same problem of displaying several at once.
do anyone know how can I solve this?
I think you may have a misunderstanding of how Adapter.getView() works its meant to create or reuse layouts when rendering the ListView it also needs to be fast so conditional manipulation in this method is discouraged. Although ListView.getChildAt() may work it does not effectively use the API. Your adapter will have a setViewBinder() unless you're using an ArrayAdapter (if so I suggest using SimpleAdapter because of the additional features). Use your ViewBinder implementation to switch the visibility of the button.
If you'd prefer to continue to use ArrayAdapter use ListView.getChildAt(int) to findViewById(R.id.your_button).setVisibility(). If this is what you already tried and its setting all the buttons visible then please post the related code.