How can I update a single row in a ListView?


Question

I have a ListView which displays news items. They contain an image, a title and some text. The image is loaded in a separate thread (with a queue and all) and when the image is downloaded, I now call notifyDataSetChanged() on the list adapter to update the image. This works, but getView() is getting called too frequently, since notifyDataSetChanged() calls getView() for all visible items. I want to update just the single item in the list. How would I do this?

Problems I have with my current approach are:

  1. Scrolling is slow
  2. I have a fade-in animation on the image which happens every time a single new image in the list is loaded.
1
128
5/10/2014 12:34:45 PM

Accepted Answer

I found the answer, thanks to your information Michelle. You can indeed get the right view using View#getChildAt(int index). The catch is that it starts counting from the first visible item. In fact, you can only get the visible items. You solve this with ListView#getFirstVisiblePosition().

Example:

private void updateView(int index){
    View v = yourListView.getChildAt(index - 
        yourListView.getFirstVisiblePosition());

    if(v == null)
       return;

    TextView someText = (TextView) v.findViewById(R.id.sometextview);
    someText.setText("Hi! I updated you manually!");
}
194
9/8/2015 1:30:49 PM

This question has been asked at the Google I/O 2010, you can watch it here:

The world of ListView, time 52:30

Basically what Romain Guy explains is to call getChildAt(int) on the ListView to get the view and (I think) call getFirstVisiblePosition() to find out the correlation between position and index.

Romain also points to the project called Shelves as an example, I think he might mean the method ShelvesActivity.updateBookCovers(), but I can't find the call of getFirstVisiblePosition().

AWESOME UPDATES COMING:

The RecyclerView will fix this in the near future. As pointed out on http://www.grokkingandroid.com/first-glance-androids-recyclerview/, you will be able to call methods to exactly specify the change, such as:

void notifyItemInserted(int position)
void notifyItemRemoved(int position)
void notifyItemChanged(int position)

Also, everyone will want to use the new views based on RecyclerView because they will be rewarded with nicely-looking animations! The future looks awesome! :-)


Licensed under: CC-BY-SA with attribution
Not affiliated with: Stack Overflow
Icon