How to avoid refreshing of cells on when calling notifyDataSetChanged() for PinterestLikeAdapterView?

前端 未结 4 1327
北恋
北恋 2021-01-05 11:36

Background

I\'m using the PinterestLikeAdapterView library to show some images from the internet, which is like a gridView but with different height for each cell.

相关标签:
4条回答
  • 2021-01-05 11:58

    There is a very good example on PinterestLikeListView in GitHub

    Here is the library StaggeredGridView

    A modified version of Android's experimental StaggeredGridView. Includes own OnItemClickListener and OnItemLongClickListener, selector, and fixed position restore.

    You can get library project here library

    and you can get Demo project Here

    This is very good open source project, so you can use instead of PinterestLikeAdapterView

    enter image description here

    Hope this library is going to help you out.

    0 讨论(0)
  • 2021-01-05 12:03

    seems that the authors of this library have fixed it, after some time i've reported about it:

    https://github.com/huewu/PinterestLikeAdapterView/issues/8

    0 讨论(0)
  • Short answer:

    Use an image loading library like Picasso that caches most recently used images in memory, so they don't need to be reloaded from the network.

    Long answer:

    AdapterView does something called View recycling, where Views which are no longer needed to display a position are re-used to display another. (For example, as you scroll down, Views that disappear off the top of the screen are reused for new positions at the bottom of the screen.) Because of this, it's normal for getView() to be passed the same View for more than one position.

    This is done for performance reasons: Inflating new Views is hard and takes time, so AdapterView tries to do it as infrequently as possible.

    When using a holder, you store references to ImageView and TextView children inside the item's View, so you don't have to look them up with findViewById() each time - you don't usually store anything specific to a particular position, because the View and its holder will often be used for different positions.

    Now, when you call notifyDataSetChanged(), AdapterView assumes that the data set has completely changed. The image that was associated with position 8 may no longer be present, or it may be associated with position 12 now. Consequently, all the existing Views are scrapped - but because AdapterView would still like to avoid inflating new Views, they're re-used to display the new data, with no regard for what position they were displaying previously.

    This explains why getView() is being passed the same View for different positions, and why visible positions are being refreshed when you call notifyDataSetChanged(). But how to avoid having your images refresh, ruining the user experience?

    Use an image loading library like Picasso that caches most recently used images in memory, so they don't need to be reloaded from the network. The refresh will still happen, but it'll be instantaneous.

    0 讨论(0)
  • 2021-01-05 12:10

    View getView(int position, View view, ViewGroup parent) will be always called ascendingly, after notifyDataSetChanged().
    I guess that, the order of finishing download task will cause this problem.
    As you mentioned in your question, keeping the position is a good way to avoid this problem.

    Here is another way to solve it, also re-use the imageviews.

    Keep a weak reference of each ImageView in download task.
    Then wrap the download task in a dummy ColorDrawable.
    When getView is called, set the dummy ColorDrawable to ImageView, and start the download. When download is complete, set the downloaded image back to the referenced ImageView in OnPostExecute().

    Explanation
    http://android-developers.blogspot.jp/2010/07/multithreading-for-performance.html
    Source code
    https://code.google.com/p/android-imagedownloader/source/checkout

    0 讨论(0)
提交回复
热议问题