JavaFX应用程序在加载许多图像时冻结几秒钟,尽管它们在后台线程中加载它们

Jas*_*ver 4 java multithreading javafx javafx-2 javafx-8

我创建了一个类作为加载器,用于在后台线程中加载图像,将它们添加到JavaFX应用程序中,

我的问题是,虽然这个类可以作为一个任务,但它会导致JavaFX Apllication在图像加载过程中冻结,并在完成后再正常工作,

装载机类代码:

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());
            }
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

从外部类调用加载器以将其添加到主JavaFX窗口中的示例:

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);
Run Code Online (Sandbox Code Playgroud)

那么我的代码中导致这些冻结的错误是什么?

谢谢 ,

Jam*_*s_D 20

您根本不需要管理线程来在后台线程中加载图像:Image构造函数有一个标志来执行此操作.做就是了

ImageView icon1 = new ImageView(new Image("http://localhost/images/1.png", true));
Run Code Online (Sandbox Code Playgroud)

等等


And*_*hev 4

问题是您通过调用以下run方法在同一线程中运行任务Runnable

new LoaderTask().run();
Run Code Online (Sandbox Code Playgroud)

常见的做法是在线程中运行它(简单):

Thread th = new Thread(new LoaderTask());
th.setDaemon(true);
th.start();
Run Code Online (Sandbox Code Playgroud)

或者将其发送到线程池(需要更多工作)。有关此内容的更多信息,请参阅相关的 Oracle 文档...

更新

如果仍然冻结:

  • 确保您不执行任何 I/O,即在 FX 线程中读取文件或资源,因为这会阻止 UI 更新并导致冻结。FX 线程是您可以更新 UI 属性的线程。
  • 尝试在单独的线程中加载资源,并在通过运行将部分/全部资源加载到内存中后立即更新场景图Platform.runLater