Respuesta corta: No, no lo es (a partir de JavaFX 2.xy 8.0). Puede ser en una versión futura (JFX> 8)
Respuesta larga: El FXMLLoader no está actualmente diseñado para funcionar como un proveedor de plantilla que crea una instancia del mismo tema una y otra vez. Más bien está destinado a ser un cargador de una sola vez para grandes GUI (o para serializarlos).
El rendimiento es pobre porque, según el archivo FXML, en cada llamada al load()
, FXMLLoader debe buscar las clases y sus propiedades a través de la reflexión. Eso significa:
- Para cada instrucción de importación, intente cargar cada clase hasta que la clase pueda cargarse satisfactoriamente.
- Para cada clase, cree un BeanAdapter que busque todas las propiedades de esta clase e intente aplicar los parámetros dados a la propiedad.
- La aplicación de los parámetros a las propiedades se realiza mediante reflexión nuevamente.
Actualmente no hay ninguna mejora para las llamadas posteriores a load()
al mismo archivo FXML realizado en el código. Esto significa: no hay almacenamiento en caché de las clases encontradas, no hay almacenamiento en caché de BeanAdapters, etc.
hay una solución para la realización de la etapa 1, sin embargo, mediante el establecimiento de un cargador de clases a medida para la instancia FXMLLoader:
import java.io.IOException;
import java.net.URL;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.Map;
public class MyClassLoader extends ClassLoader{
private final Map<String, Class> classes = new HashMap<String, Class>();
private final ClassLoader parent;
public MyClassLoader(ClassLoader parent) {
this.parent = parent;
}
@Override
public Class<?> loadClass(String name) throws ClassNotFoundException {
Class<?> c = findClass(name);
if (c == null) {
throw new ClassNotFoundException(name);
}
return c;
}
@Override
protected Class<?> findClass(String className) throws ClassNotFoundException {
// System.out.print("try to load " + className);
if (classes.containsKey(className)) {
Class<?> result = classes.get(className);
return result;
} else {
try {
Class<?> result = parent.loadClass(className);
// System.out.println(" -> success!");
classes.put(className, result);
return result;
} catch (ClassNotFoundException ignore) {
// System.out.println();
classes.put(className, null);
return null;
}
}
}
// ========= delegating methods =============
@Override
public URL getResource(String name) {
return parent.getResource(name);
}
@Override
public Enumeration<URL> getResources(String name) throws IOException {
return parent.getResources(name);
}
@Override
public String toString() {
return parent.toString();
}
@Override
public void setDefaultAssertionStatus(boolean enabled) {
parent.setDefaultAssertionStatus(enabled);
}
@Override
public void setPackageAssertionStatus(String packageName, boolean enabled) {
parent.setPackageAssertionStatus(packageName, enabled);
}
@Override
public void setClassAssertionStatus(String className, boolean enabled) {
parent.setClassAssertionStatus(className, enabled);
}
@Override
public void clearAssertionStatus() {
parent.clearAssertionStatus();
}
}
Uso:
public static ClassLoader cachingClassLoader = new MyClassLoader(FXMLLoader.getDefaultClassLoader());
FXMLLoader loader = new FXMLLoader(resource);
loader.setClassLoader(cachingClassLoader);
Esto acelera significativamente el rendimiento. Sin embargo, no hay ninguna solución para el paso 2, por lo que esto podría ser un problema.
Sin embargo, ya hay solicitudes de funciones en la jira JavaFX oficial para esto. Sería amable de su parte apoyar estas solicitudes.
Enlaces:
http://javafx-jira.kenai.com/browse/RT-23413
http://javafx-jira.kenai.com/browse/RT-23511
Fabulosa respuesta Sebastian – jewelsea
Los enlaces al final ya no son válidos. ¿Alguien sabe lo que solían señalar y puede encontrar el JDK actualizado? ID correspondiente a ellos? – Itai