Yesterday I wrote about some JavaFX Internals…. Today comes the second part.
Today we start to use some of the JavaFX classes by Java. Therefore I just added all JavaFX jars to the classpath.
Extending FXBase
It is a very good idea to extend FXBase. We just have to figure out which methods have to be called for initialization. Following the samples, our class could look like that:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22
| import com.sun.javafx.runtime.FXBase;
import com.sun.javafx.runtime.FXObject;
import com.sun.javafx.runtime.annotation.Public;
@ Public
public class Run extends FXBase implements FXObject {
public static void main ( String[] args ) {
System. out. println( "Starting!" );
System. out. println( "Finished" );
}
public Run () {
this( false );
initialize$ ( true );
}
public Run ( boolean paramBoolean ) {
super( paramBoolean );
}
} |
Approaching that binding stuff
As mentioned yesterday the magic happens within the DependentsManager. Thankfully that sources are available…
One key is the WeakBinderRef that can be stored within each FXObject and be retrieved calling getThisRef$internal$().
There is a static method that creates those refs lazyly: WeakBinderRef.instance().
This WeakBinderRef contains the dependencies for this object. The field bindees contains a chain of Dep instances. Interestingly the WeakBinderRef for test does not contain any bindees as one might have expected. Those are the reverse dependencies!
The “real” dependencies are stored within each object within the field DepChain$internal$ (of type DepChain).
Relevant is the bindeeVarNum. Here is the var num stored that dependency is based upon.
Process of dependency notification
Whenever a var is changed, there are two calls made to notifyDependents$. They can be distinguished by the phase (argument).
That methods uses the DependentsManager to call invalidate on all depending objects. Those simply change the flag so that the next time the var is accessed, it can be resolved again.
While the binding performance in JavaFX is much better in 1.3 it is still not really lazy. There happen a lot of calls until the value is marked as invalid.
So I assume that the performance has just been increased for complex binding expressions. Just binding one var to another shouldn’t be much faster now (this is just an assumption!)…
Adding dependencies manually
Now we try to add a dependency manually. It is possible by simply calling “DependentsManager.addDependent()“.
Of course it does not have any visible effects (besides that the update/invalidate methods are called). Because the values are fetched from the original objects… But the debugger shows us, that it is possible to use that bind mechanism from Java.