سؤال

I have a GridView containing ImageViews, I would like to refresh the Views if an image is successfully downloaded and converted into a Bitmap object. The GridView's adapter has a getView method that can set a default image or decode to Bitmap the downloaded image if it exists.

To refresh the GridView I can use the myGridView.getAdapter().notifyDataSetChanged() method, so I created a BroadcastReceiver able to detect if a successfully downloaded file is one of the images I need and eventually send a Listener event to the activity containing the GridView to refresh it. Since the GridView adapter can even contain thousands of elements, I would like to execute launch notifyDataSetChanged only if the View for that specific file is visible.

I thought to do something like this:

for(int i=0;i<myGridView.getChildCount();i++){
    if(myGridView.getChildAt(i).isTheOneINeed) { //notifyDataSetChanged(); break; }
}

But I'm a bit concerned: what if the user scrolls the GridView and the childView becomes null or it's replaced by one of the next items in the Adapter? Is there a safer way to do this?

هل كانت مفيدة؟

المحلول

My personal opinion is you should not play with ListView/GridView children (unless you REALLY need to). If your data has changed you should call notifyDataSetChanged(). ListView/GridView will redraw just a few items (those that are visible), even if you have thousands of them.

To optimize your code and call notifyDataSetChanged() only when the item is visible, you can get the first and last visible positions by calling getFirstVisiblePosition() and getLastVisiblePosition()

نصائح أخرى

I'm guessing that your Activity uses an AsyncTask to download images, which are then decoded in the Adapter's getView() method. If the user of your app scrolls up and down too quickly, then your images can get blurred / swapped and your app can become unresponsive as the AsyncTask threads go crazy trying to cope with the downloading & caching and your Adapter struggles with the decoding.

Have you heard of the new Volley networking library for Android ? It's developed at Google (its a part of the AOSP). I suggest you give it a try as it is asynchronous by default (it abstracts away the downloading, caching & decoding while providing a very clean interface to the developer). I'm using it for HTTP requests & image downloading, and its very fast and stable. You can even control thread priority & cancellation. There is no blurring or stuttering of listviews / gridviews, and it can handle very large images with ease. Picasso is another great option for the image downloading part. Picasso is slightly slower than Volley for downloading images, but its just as stable and TRIVIAL to integrate (one line of code in your adapter).

Volley and Picasso work beautifully even if you don't add the notifyDatasetChanged() method to your Adapter's getView() (though of course it is good practice to do so). As the getView() method is called on demand, both only download the image when the user scrolls down.

See an example of image downloading with Volley here.

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top