The GridView is being filled every time I do something


#1

Hello, I am not sure if I missed an step but something is happening and my experience so far is not enough to find the problem (Even when I debugged it many times).

Scenario:

No search saved. Recent images appear. (Good)
I click on search, the ActionBar changes to show the textbox and seems like my fragment is re-shown again, because I see the brian faces again, then the recent images appears again.
The soft keyboard appears, I hide it, and brian faces appears again, then recent images again.
I click on the textbox, soft keyboard appears, and it reloads the images again (this can be infinite).

I decide I want to search, I put… “Car” , I accept and then brian faces again, recent images, then brian faces, then cars.

If I want to search something else, the same.

TL;DR; Every time (I guess) the fragment refresh, the old items appears again, no matter if they are the recent images or the last search. The idea is that items won’t appear every time I show/hide the keyboard or I show/hide the search box. And of course is not good to search for something and see the last result again before it really search.

I guess that none of our code does this, this is something behind the curtain, default behavior of the fragment and the adapter.

Thanks and I love this book :slight_smile:


#2

Interesting. Is this with the SearchView, on a Honeycomb+ device? I’m not seeing the behavior you describe.


#3

Both, Gnex 4.3 and a froyo emulator. I am not using the SearchView, it gave me null exception when I tried to use it. Maybe I should research it more to see what happened and see if using that I can solve my problem on Honeycomb+. Anyway it would happen in Froyo.

Another thing is that I am using appcompat v7 so the froyo version has ActionBar, AKA “SingleFrameActivity” extends ActionBarActivity for that compatibility.

I’ll research and put my results here.


#4

Interesting. I’ve removed the action view class and related code from my sample, and I’m unable to replicate.

One question I’d be interested in knowing the answer to: where in your code is updateItems() called?


#5

They have nothing to do. I tried to debug my app, and updateItems() was my first guess. They are called when the data is shown the first time, but if I show the Search box (and every time I show/hide the soft keyboard), the view is redrawn and no updateItems() is called. In fact I am unable to find any line of code that is being called every time I do that.

Anyway, I use it (updateItems) on menu_item_clear, onCreate() (onCreate is not being called on the redrawns) and in PhotoGalleryActivity’s onNewIntent.

I am still not able to see if any of my code is being called over and over that is forcing a refresh.

If you have curiosity (I mean, I can investigate it on my own, I just thought that you would know about the problem) I can put on github (it is a android studio project).


#6

Did you try it on real phone?

Seems like it works good in emulators, 4.3, 4.4… But in my phone it doesn’t. I don’t have other android to try. (I changed the rom and tried again, no luck).


#7

I am having the same issue. Was a resolution ever found? I am using a real phone with 4.1.2 on it.


#8

This happens because Android is re-painting the screen after displaying and/or removing the Search activity. Each time Android does this, the getView method in the GalleryItemAdapter is called for each of the images that are currently in view on the screen, and this method puts Brian’s face back into the associated ImageView and then queues a request to the thumbnail downloader thread to re-request the relevant image.

The solution is to use an LruCache to save each bitmap after it has been downloaded, and to check the cache in the getView method to see if we have already downloaded a copy of the required bitmap, and if so simply update the ImageView with the cached bitmap.

To do this, add the following line after the definition of mThumbnailThread in PhotoGallerFragment:

[color=#FF0000] LruCache<String, Bitmap> mCache;[/color]

Add the following lines to PhotoGalleryFragment.onCreate, after the call to super.onCreate:

[color=#FF0000]
final int maxMemory = (int) (Runtime.getRuntime ().maxMemory () / 1024);
final int cacheSize = maxMemory / 8;

    mCache = new LruCache<String, Bitmap> (cacheSize) {
        @Override
        protected int sizeOf (String key, Bitmap bitmap) {
            return (bitmap.getByteCount () / 1024);
        }
    };

[/color]

Add a couple of cache management helper functions to PhotoGalleryFragment:

[color=#FF0000]
private void addBitmapToCache (String url, Bitmap bitmap) {
if (getBitmapFromCache (url) == null)
mCache.put (url, bitmap);
}

private Bitmap getBitmapFromCache (String url) {
    return (mCache.get (url));
}

[/color]

Modify the onThumbnailDownloaded method of the ThumbnailDownloader.Listener interface to include a String parameter for the URL, and change the relevant code in PhotoGalleryFragment.onCreate to cache the retrieved bitmap after updating the ImageView, as follows:

[color=#FF0000]
mThumbnailThread = new ThumbnailDownloader (new Handler ());
mThumbnailThread.setListener (new ThumbnailDownloader.Listener () {
public void onThumbnailDownloaded (ImageView imageView, String url, Bitmap bitmap) {
if (isVisible ()) {
imageView.setImageBitmap (bitmap);
addBitmapToCache (url, bitmap);
}
}
});
[/color]

Modify the ThumbnailDownloader.handleRequest method to pass the URL when it calls mListener.onThumbnailDownloaded, and finally modify the GalleryItemAdapter.getView method to check the cache before hitting the web, as shown:

[color=#FF0000]
@Override
public View getView (int position, View convertView, ViewGroup parent) {
if (convertView == null)
convertView = getActivity ().getLayoutInflater ().inflate (R.layout.gallery_item, parent, false);

        GalleryItem item = getItem (position);
        ImageView imageView = (ImageView) convertView.findViewById (R.id.imageView);
        Bitmap bitmap = getBitmapFromCache (item.getURL ());

        if (bitmap != null) {
            imageView.setImageBitmap (bitmap);
            return (convertView);
        }

        imageView.setImageResource (R.drawable.brian_up_close);
        mThumbnailThread.queueThumbnail (imageView, item.getURL ());
        return (convertView);
    }

[/color]

Chris