List filtering and JList indexes trouble.

classic Classic list List threaded Threaded
4 messages Options
Reply | Threaded
Open this post in threaded view
|

List filtering and JList indexes trouble.

i30817
Hi. I'm trying to create a image JList, and using a disk based cache to remove the possibility of outofmemory exceptions.
To do this, i have a CellRenderer that displays the images and for any image that is not visible then, disposes it from the memory cache (to force to get from the disk cache). The memory cache is a Map<Integer listindex, Image image> mapping.

The mapping is something like this:
int firstIndex = list.getFirstVisibleIndex();
                int lastIndex = list.getLastVisibleIndex();
                Iterator<Integer> mapKeyIterator = memoryCache.keySet().iterator();
                while(mapKeyIterator.hasNext()){
                    Integer key = mapKeyIterator.next();
                    if(key < firstIndex || key > lastIndex){
                        Image img = memoryCache.get(key);
                        if(img != null){
                            mapKeyIterator.remove();
                            img.getGraphics().dispose();
                        }
                    }
                }

Trouble is this mapping won't work from a EventListModel from a (filtered) FilterList, since then the mappings are wrong - and not consecutive even if they were right. Anyone can think of a alternative (i'd still like to accept any ListModel). Can you think of any alternative mapping or a way that i can bend the passed list model?
Reply | Threaded
Open this post in threaded view
|

Re: List filtering and JList indexes trouble.

James Lemieux
Hey there,

   My opinion is that mapping indexes to Images directly is a flimsy design for some of the reasons you have already found. I would make my JList display "container objects" that know how to provide an image on demand regardless of whether the image is currently in memory or not. It would look something like:

public class ImageContainer {
   private WeakReference<Image> imageRef;

   private final String fileName;

   public ImageContainer(String fileName) {
      this.fileName = fileName;
   }

   public Image getImage() {
      // check our weak cache first
      Image image = imageRef == null ? null : imageRef.get();

      // image will be null if either:
      //    a) this is the first time it has been requested
      //    b) the Garbage Collector chose to discard the imageRef's contents
      if (image == null) {
         // load the image on demand now and cache it weakly
         image = loadImageFromDisk(fileName);
         imageRef = new WeakReference<Image>(image);
      }

      return image;
   }

   private static Image loadImageFromDisk(String fileName) {
      ...
   }
}

In this implementation each ImageContainer is capable of loading and caching its Image, but since the caching is done weakly it will never be the cause of memory problems in your JVM. This design essentially allows your Garbage Collector to control your eviction policy for Images from memory instead of you (as is the case when hard references are used).

Once you have converted to using ImageContainers (or some similar concept) you can filter, sort, slice and dice them as much as you want, but each ImageContainer can still "stand on its own and return you its image", regardless of its index in any given EventList or data structure...

James

On Tue, Apr 7, 2009 at 7:19 PM, i30817 <[hidden email]> wrote:

Hi. I'm trying to create a image JList, and using a disk based cache to
remove the possibility of outofmemory exceptions.
To do this, i have a CellRenderer that displays the images and for any image
that is not visible then, disposes it from the memory cache (to force to get
from the disk cache). The memory cache is a Map<Integer listindex, Image
image> mapping.

The mapping is something like this:
int firstIndex = list.getFirstVisibleIndex();
               int lastIndex = list.getLastVisibleIndex();
               Iterator<Integer> mapKeyIterator =
memoryCache.keySet().iterator();
               while(mapKeyIterator.hasNext()){
                   Integer key = mapKeyIterator.next();
                   if(key < firstIndex || key > lastIndex){
                       Image img = memoryCache.get(key);
                       if(img != null){
                           mapKeyIterator.remove();
                           img.getGraphics().dispose();
                       }
                   }
               }

Trouble is this mapping won't work from a EventListModel from a (filtered)
FilterList, since then the mappings are wrong - and not consecutive even if
they were right. Anyone can think of a alternative (i'd still like to accept
any ListModel). Can you think of any alternative mapping or a way that i can
bend the passed list model?

--
View this message in context: http://www.nabble.com/List-filtering-and-JList-indexes-trouble.-tp22941893p22941893.html
Sent from the GlazedLists - Dev mailing list archive at Nabble.com.


---------------------------------------------------------------------
To unsubscribe, e-mail: [hidden email]
For additional commands, e-mail: [hidden email]


Reply | Threaded
Open this post in threaded view
|

Re: List filtering and JList indexes trouble.

i30817
Eventually i went in other direction, since i don't (want to) control the passed listmodel-
Instead of a index -> Image mapping i used a (list) Object -> Image mapping. I'm using this for the indexes to be always consistent even with mutable listmodels. I also don't control the Image getting policy. In particular it can even be in another thread (and is in my implementation).

I don't trust weak references, since the memory is only going to be reclaimed when the GC feels pressured. In particular i'm allocating huge arrays somewhere else. The approach i used uses the JList natural lazy painting to only have in memory the visible cells at the time, and the other are disposed/need to be refetched.

This is very much more complicated, but i think it is flexible... somewhat, for this purpose only. If you're curious how it works/looks see my newly created blog here:
http://swingblognotthatkind.blogspot.com/
Reply | Threaded
Open this post in threaded view
|

Re: List filtering and JList indexes trouble.

James Lemieux
"I don't trust weak references, since the memory is only going to be
reclaimed when the GC feels pressured."

You have described SoftReferences, not WeakReferences.

WeakReference'd objects are GCable the moment they are no longer reachable via hard references (regardless of the amount of VM memory consumed), which seems to be your intended behaviour.

James

On Wed, Apr 8, 2009 at 12:55 PM, i30817 <[hidden email]> wrote:

Eventually i went in other direction, since i don't (want to) control the
passed listmodel-
Instead of a index -> Image mapping i used a (list) Object -> Image mapping.
I'm using this for the indexes to be always consistent even with mutable
listmodels. I also don't control the Image getting policy. In particular it
can even be in another thread (and is in my implementation).

I don't trust weak references, since the memory is only going to be
reclaimed when the GC feels pressured. In particular i'm allocating huge
arrays somewhere else. The approach i used uses the JList natural lazy
painting to only have in memory the visible cells at the time, and the other
are disposed/need to be refetched.

This is very much more complicated, but i think it is flexible... somewhat,
for this purpose only. If you're curious how it works/looks see my newly
created blog here:
http://swingblognotthatkind.blogspot.com/
--
View this message in context: http://www.nabble.com/List-filtering-and-JList-indexes-trouble.-tp22941893p22957620.html
Sent from the GlazedLists - Dev mailing list archive at Nabble.com.


---------------------------------------------------------------------
To unsubscribe, e-mail: [hidden email]
For additional commands, e-mail: [hidden email]