Redraw a single row in a listview
android, android-arrayadapter, listview, redraw, view
Solution
As Romain Guy explained a while back during the Google I/O session, the most efficient way to only update one view in a list view is something like the following (this one update the whole `View` data):
ListView list = getListView();
int start = list.getFirstVisiblePosition();
for(int i=start, j=list.getLastVisiblePosition();i<=j;i++)
if(target==list.getItemAtPosition(i)){
View view = list.getChildAt(i-start);
list.getAdapter().getView(i, view, list);
break;
}
Assuming `target` is one item of the adapter.
This code retrieve the `ListView`, then browse the currently shown views, compare the `target` item you are looking for with each displayed view items, and if your target is among those, get the enclosing view and execute the adapter `getView()` on that view to refresh the display.
As a side note `invalidate()` doesn't work like some people expect and will not refresh the view like `getView()` does, `notifyDataSetChanged()` will rebuild the whole list and end up calling `getview()` for every displayed items and `invalidateViews()` will also affect a bunch.
One last thing, one can also get extra performance if he only needs to change a child of a row view and not the whole row like `getView` does. In that case, the following code can replace `list.getAdapter().getView(i, view, list);` (example to change a `TextView` text):
((TextView)view.findViewById(R.id.myid)).setText("some new text");
In code we trust.
Problem
Is it possible to redraw a single row in a `ListView`? I have a `ListView` with rows that are `LinearLayout`s. I listen to a preference change and sometimes I need to change just one `View` inside the `LinearLayout` of a single row. Is there a way to make it redraw that row without calling `listview.notifyDatasetChanged()`? I've tried calling view.invalidate() on the view (inside the `LinearLayout`) but it doesn't redraw the row.