How to avoid re-drawing all views in an ArrayAdapter - android

I have an ArrayAdapter powering a ListView. I would like to change the data behind the ArrayAdapter and update the ListView's. Sounds like notifyDataSetChanged(); would be exactly what I am looking for, but it updates the entire ListView, and I would prefer to update on a row-by-row basis.
Is there a way to do this with ArrayAdapter, or do I need to manage my data some other way if I want this functionality?

It doesn't work like that, as far as I know.
It will only redraw the visible rows. This happens when you're scrolling anyway. If you're scrolling down, and one of your rows (a View) goes off the top, Android reuses it if possible when drawing rows that come into view from the bottom. This is what the 3rd parameter (convertView) of ListAdapter.getView() is for.
I'm pretty sure Android only draws the rows that you're able to see in any case.

Related

Android engineering: ListView versus just a dynamic LinearLayout

When you are working with a long, big list, certainly one should use ListView because it handles cell recycling.
Notice here, for example Can i use nested linearlayouts instead of list view, for a big list? the OP is asking about ListView verses a dynamic LinearList -- the answer is "have to use a ListView, because of recycling"
Now, say you are making a short list -- imagine say a popup with only 10 or 20 items. It may even fit all on the one screen, so there's no recycling.
In fact, is there any difference between using a ListView and just using a LinearLayout, and dynamically populating the little views inside it?
It seems to me that the latter is in many cases much simpler, more elegant, and easier to work with. But I could well be missing something that seasoned Android engineers know about.
Should I just use an ordinary LinearList (populate it dynamically) for lists where recycling is not relevant? What's the usual, and why? Cheers!
{Incidentally, for popup cases, is there some better, lightweight method for "choose one from a popup-list" that I'm too silly to know about?! :) )
ListView(and other lists) supports very useful idea: splitting data and view. These parts could be changed at any time so it's important to support flexibility. And it could be solved by special mediator object: Adapter. Adapter roughly speaking says how to fill your view with particular data item.
So I'm sure that if you decide to use LinearLayout sooner or later you will implement you own Adapter.
If you used dynamic linear view then rendering the view will take more time as compare to listview. In listview we are rendering views which are visible only but if you used dynamic linear view then its problem.

Showing animation of Views created from a custom adapter

I'm trying to show an animation with all Views that I've created from an adapter. When I scroll down, it shows the animation correctly, but when I scroll up, I see these Views recreate themselves and show the animation again. Then, when I scroll down, it happens again.
My assumption is that the mechanism of creating a View from an adapter is to load the View into memory; just the group of Views which are on screen right now (but above and below views are not loaded into memory). These will be loaded again when I scroll to these views, right?
Is there any way to fix this problem?
PS: Sorry for my English, I hope you understand my problem.
My assumption is that the mechanism of creating a View from an adapter
is to load the View into memory; just the group of Views which are on
screen right now (but above and below views are not loaded into
memory)
That's somewhat correct: a ListView will not try to visualize any data that isn't (at least partially) visible. It also 'recycles' views, meaning that any view that isn't currently used to present data to the user and is of the same 'type' as the next data item, may get reused.
Hence you shouldn't rely on persisting data with or make any assumptions about the existence of particular views. In stead, use something that's separate from the views; e.g. the dataset you're visualizing.
Quite often, you'll supply a list of POJOs to a BaseAdapter or ArrayAdapter. You could simply add a boolean to the POJO indicating whether it should animate or not, and change that whenever the animation for that particular item finishes. Alternatively, you could keep track of these values in a separate collection (which is probably the more straightforward approach if you're dealing with a Cursor as data source rather than POJOs).

Android viewpager, control which views to re-render

my viewpager currently only re-renders views that are two views away from what is visually seen.
example (shown respectively)
ViewA, ViewB, CurrentView, ViewD, ViewE
not rendered, rendered, rendered, rendered, not rendered`
how would I force it to reload a particular view X many views away from the currentView, there are some use case scenarios where I want it to, and other cases when I dont want it to. But currently I only know how to reload the entire adapter - where it perhaps pulls from an arraylist
I'm really not sure how to control the Viewpager - very few examples out there. All I know how to do is reset the entire list on "notifyDataSetChanged"
insight appreciated
use this method mViewPager.setOffscreenPageLimit(2) and you can set the limit of offscreen pages
I think your going too need to decouple your view and data logic (array list in this case?). If you don't want the view to change, don't change the data layer. When you call notifyDataSetChanged everything will mimic your data layer. If you want a view to change, change the data layer and call notifyDataSetChanged.
To put it simpler, the view just draws what the data tells it to, and expect that the view could update at any time. It is very similar to how listview works.

Is there a way to call BaseAdapter.notifyDataSetChanged() on a single object?

Is there a way to call BaseAdapter.notifyDataSetChanged() on a single element in the adapter.
What I am trying to do is update the data and reflect those changes in the containing ListView. The problem is that sometimes the change is so small that it seems ridiculous that I have to refresh the whole view rather than the single item in the view that has been updated.
I am not aware of such method. If it's really important, you can always find individual item view to update. But I don't think that it worth it as Android is pretty efficient in updating list views. So it will not do much extra work (definitelly not going beyond items currently visible on the screen).

Should I use multiple ListViews?

I have a RelativeLayout with different elements. I was planning to have two ListViews on it, but I have noticed there are some problems with scrolling. Since each ListView only shows a maximum of 5 rows should I try to make some kind of custom adapter to merge those ListViews? Or is it better to replace the ListView with a LinearLayout/RelativeLayout and add the rows as I get them manually? (like the first answer in here: android listview display all available items without scroll with static header ).
Which should be the proper way on doing this? or is there another way? Also, each row will have an OnClickListener.
There's two solutions if you'd like to keep your list... list-y, without having to prerender all the row Views like the above solution suggests (which can be slow to render, eats RAM and doesn't scale nicely to more than a screen or two of Views, but is a fine quick solution for smaller lists, though I'd just use a bunch of Views in a LinearLayout in a ScrollView rather than a ListView in that case).
Write a custom ListAdapter, overriding getItemViewType, getViewTypeCount and GetView to inflate the proper kind of view and recycle appropriately for your two types of views. You'll also either need to override getItem to contain custom logic for figuring out which set of source data to look in and to map the data accordingly, or mush the data down into one list of Objects (if you're using an arrayadapter) and cast in the getView method (probably a bit slower than handling it in the getItem without casting).
Just use cwac-merge, a view-and-adapter wrapping adapter. You can put two ListAdapters into a MergeAdapter and set that as your single ListView's adapter.
I had problems with scrolling. I never figured out how to have the ListView share vertical space with a different View, and have a single scrollbar for them both.
I worked around it by having everything that needs to scroll on the layout a row in the ListView.
Adding views as rows to a LinearLayout may have problems scaling up, but I think you'll be OK if you only have 10 rows in total. On 1st gen Android devices it'll probably start to get sluggish around 20 items (depends on Layout complexity obviously). ListView scales up by only inflating views as they come on screen.
So in answer to your question either of the two alternatives you suggest will be OK, but the LinearLayout option will be the easiest to code.

Categories

Resources