JavaFX Application freeze some seconds when load many images although of loading them in background Thread


Question

i made a class as a loader for loading images in background Thread , to add them inside the JavaFX Application ,

my problem is , although of this class works as a Task , but it cause the JavaFX Apllication freeze during images loading , and work back again normally after it finish,

The Loader Class Code :

import javafx.concurrent.Service;
import javafx.concurrent.Task;
import javafx.scene.image.Image;
import javafx.scene.image.ImageView;

public class Loader{
    private String type     = "";
    private String url      = "";
    private ImageView image = new ImageView();

    private class LoaderService extends Service{
        @Override
        protected Task createTask() {
            return new LoaderTask();
        }
    }

    private class LoaderTask extends Task{
        @Override
        protected Object call() throws Exception {
            new LoaderClass();

            return null;
        }
    }

    private String getType(){
        return this.type;
    }

    private String getUrl(){
        return this.url;
    }

    public Loader type(String type){
        this.type = type;
        return this;
    }

    public Loader url(String url){
        this.url = url;
        return this;
    }

    public ImageView getImage(){
        return this.image;
    }

    public Loader build(){
        new LoaderTask().run();
        return this;
    }

    private class LoaderClass{
        public LoaderClass(){
            switch(getType()){
                case "image":
                    this.loadImage(getUrl());
                break;
            }
        }

        private void loadImage(String url){
            try{
                getImage().setImage(new Image(url));
            }catch(Exception ex){
                System.out.println("Ex"+ex.getMessage());
            }
        }
    }
}

Example of calling the loader for images from external class to add them inside the main JavaFX Window :

StackPane Pane = new StackPane();

ImageView Icon1 = new NinjaLoader()
                                    .type("image")
                                    .url("http://localhost/images/1.png")
                                    .build()
                                    .getImage();

ImageView Icon2 = new NinjaLoader()
                                    .type("image")
                                    .url("http://localhost/images/2.png")
                                    .build()
                                    .getImage();

ImageView Icon3 = new NinjaLoader()
                                    .type("image")
                                    .url("http://localhost/images/3.png")
                                    .build()
                                    .getImage();

ImageView Icon4 = new NinjaLoader()
                                    .type("image")
                                    .url("http://localhost/images/4.png")
                                    .build()
                                    .getImage();
Pane.getChildren().addAll(Icon1,Icon2,Icon3,Icon4);

so what is the wrong in my code which cause these freezes ?

Thank you ,

1
4
12/26/2013 9:46:01 PM

Accepted Answer

The issue is that you're running your task in the same thread by calling run method of Runnable:

new LoaderTask().run();

The common practice is to run it in a thread (simple):

Thread th = new Thread(new LoaderTask());
th.setDaemon(true);
th.start();

or to send it to a thread pool (a bit more work). More on this in the related Oracle docs...

UPDATE

If it still freezes:

  • Make sure you don't do any I/O, i.e. reading files or resources in the FX thread, as this would block UI updates an cause the freeze. FX thread is the thread from which you are able to update your UI properties.
  • Try loading resources in a separate thread and update Scene Graph as soon as some/all of them are loaded into memory by running Platform.runLater.
4
12/26/2013 10:29:27 PM

You don't need to manage threading at all to load images in a background thread: the Image constructor has a flag to do this. Just do

ImageView icon1 = new ImageView(new Image("http://localhost/images/1.png", true));

etc.


Licensed under: CC-BY-SA with attribution
Not affiliated with: Stack Overflow
Icon