Search code examples
javaimagejavafximageviewbackground-process

How can I find out that JavaFX Image loading in background has failed?


Question in short:

How can I find out, that background loading of image has failed just before imageView.setImage(image) results in showing an empty picture although image.isError==false and image.getException==null?

Background:

In my simple JavaFX based photoviewer app I use a TableView() for showing a directory with jpg files. Whenever one selects an entry in the table the picture is loaded using javafx Image class and is shown using an ImageView.

I load the photos in background using true in the parameter of the Image-constructor. Once a photo is loaded I keep it in a list ("Cache") for faster "showing again"

Here the code snippet:

public Object getMediaContent() {
Image image = (Image) content;

if (!isMediaContentValid()) {  //if not already loaded or image in cache is invalid
  try {
    System.out.println("getMediaContent loading " + fileOnDisk);
    content = new Image(fileOnDisk.toUri().toString(), true);  //true=load in Background
  } catch (Exception e) {
    //will not occur with backgroundLoading: image.getException will get the exception
    System.out.println("Exception while loading:");
    e.printStackTrace();
  }
} else {
  System.out.println(fileOnDisk.toString() + "in Cache :-)...Error="+ image.isError() + " Exception=" + image.getException());
}
return content;

}

In isMediaContentValid() I test

  • if the image is already in the cache's list
  • and if image.isError() is false
  • and if image.getException() is null

The problem:

When the user selects photos very quickly (e.g. by using cursor down key) images are still loaded in background (for the cache) while the next photo's loading has already started. My simple chache algorithm has problems to find out when I run out of memory because there might be enough memory when loading is started but not to complete all background tasks.

But I expected that this is not a problem because image.isError() would report true or image.getException() would be != null in this case. So I could free memory before retrying.

But isError() reports false, getException() reports null and the image is shown "empty" in imageView :-(

The question: How can I find out, that background loading of image has failed just before imageView.setImage(image)?


Solution

  • How can I find out, that background loading of image has failed just before imageView.setImage(image)?

    This is not possible. The whole point of loading the image in the background is that it's done asynchronously. There is no guarantee that the exception already occured at the time the method returns. You need to use a listener to the error property to be notified of a failure to load the image.

    Example

    Image image = new Image("https://stackoverflow.com/abc.jpg", true); // this image does not (currently) exist
    image.errorProperty().addListener(o -> {
        System.err.println("Error Loading Image " + image.getUrl());
        image.getException().printStackTrace();
    });