java - JavaFX. Where to put service class reference? Controller or Main app starter class? -
i work javafx application , use fxml implement mvc pattern. make proof of concept, , start create javafx user interface.
in previous experience spring mvc, there usual create service , inject them in controller class via annotations. javafx cannot find recommendations how that. not sure have put services controller, or call main class method controller. second solution holds service reference in main application class.
please note application runs service classes in concurrent threads. of them implements runnable interface
i avoid having controllers needing refer main application class introduces dependency not necessary. have each controller keep reference service object.
to provide service controllers, can use 1 of techniques outlined in this question.
there 3 ways this:
creating controller , setting in fxmlloader
directly
in version, do not use fx:controller
attribute in root element of fxml file (doing cause exception thrown).
given
public interface service { ... }
and
public class somecontroller { private final service service ; public somecontroller(service service) { this.service = service ; } // ... }
then can load fxml file
service service = ... ; fxmlloader loader = new fxmlloader(getclass().getresource("path/to/fxml/file.fxml")); somecontroller controller = new somecontroller(service.class); loader.setcontroller(controller); parent uiroot = loader.load();
retrieving controller fxmlloader
, setting service
if want able use fx:controller
attribute, controller class must have no-argument constructor. in case, can set service on controller after fxmlloader
has completed loading. looks like:
public class somecontroller { private service service ; public void initservice(service service) { this.service = service ; // update ui values service... } // ... }
note here have refactor code initialize()
method, code may depend on service, not have been set when initialize()
invoked. move such code initservice(...)
method. loading fxml file looks like
service service = ... ; fxmlloader loader = new fxmlloader(getclass().getresource("path/to/fxml/file.fxml")); parent uiroot = loader.load(); somecontroller controller = loader.getcontroller(); controller.initservice(service);
using controller factory
the third approach uses controller factory. more complex, has advantages. in particular, if fxml file uses fx:include
tags, controller factory reused when included fxml files loaded, controllers can have service object initialized well. managing included fxml files above 2 approaches possible, little convoluted.
the controller factory function maps class<?>
controller should used (presumably 1 of class, though there requirement that). default controller factory invokes newinstance()
on class<?>
object (which why need no-arg constructor). here general controller factory implementation calls constructor taking service
parameter if 1 exists, , calls no-arg constructor if not.
service service = ... ; callback<class<?>, object> controllerfactory = type -> { try { (constructor<?> c : type.getconstructors()) { if (c.getparametercount() == 1 && c.getparametertypes()[0] == service.class) { return c.newinstance(service); } } return type.newinstance(); } catch (exception e) { throw new runtimeexception(e); } };
you can create once , use fxml load (note references single service
instance):
fxmlloader loader = new fxmlloader(getclass().getresource("path/to/fxml/file.fxml")); loader.setcontrollerfactory(controllerfactory); parent uiroot = loader.load();
this work fx:controller
attribute if refers class constructor taking service
parameter (such first controller example above).
if used dependency-injection frameworks, might interested in afterburner.fx adam bien. works setting controller factory examines controller class @inject
annotations , sets values on controller, have annotate service field in controller , follow specific afterburner.fx naming conventions, , happens automagically.
i recommend this article, adam bien, discusses strategies communicating services controller (including handling concurrency issues).
Comments
Post a Comment