Can I create weak bindings in JavaFX? - binding

I have two bound StringProperty objects. I want the Binding to be weak, so that it becomes eligible for garbage collection as soon one of the bound objects has been GCed.
See this example:
StringProperty obj1 = new StringProperty("Object1");
StringProperty obj2 = new StringProperty("Object2");
obj2.bind(obj1);
obj2 = null;
How can I create a weak reference, so that the Bindung created in line 3 can be collected?

Although a late anwser, I found this snippet in the Property.bind(...) JavaDoc:
Note that JavaFX has all the bind calls implemented through weak listeners. This means the bound property can be garbage collected and stopped from being updated.
Therefore your bindings should maintain weak references by default.

If you use a BidirectionalBinding via property1.bindBidirectional(property2) or in your case obj2.bindBidirectional(obj1) this binding will be created using com.sun.javafx.binding.BidirectionalBinding which is implented using WeakReference.
If this is what you are searching, it works as expected. If you are "only" interested in an unidirectional binding, you can go on to the source code of the aforementioned class, copy its binding implementation and tailor it to your needs.

Why don't you create a custom-string-binding. Then you can handle the null-case yourself when the binding is activated.

Related

Can I recall a Stateful Class while in the class

I am passing the first object of a List myList[] from Class A to a stateful class B that is a separate page in my application. The passed object is therefore created as immutable since flutter prefers immutable classes and immutable classes need const constructors, variables in which must be final. In the B class, I later call a function that modifies the object from the List, and objects in a list aren't immutable. But since I have already passed the object, I can't see the updated value. I solved this issue by making: the value - non-final, the constructor - not const, and therefore the class - mutable. Another way I could solve it is to just use global variables instead.
My question is - Is there a way to reinstantiate class B? I.e., go to class A, navigate to page B by passing the (now updated) first object of List myList[] ?
Perhaps you could try using a State manager like Provider. From my understanding, you're trying to share variables across different widgets. Using a state management library seems to do exactly what you want.

Creating a listener on a list for changes

I have a dart object which contains a list. Simply put:
class Test extends PolymerElement{
List list = [];
addTask(item){
list.add(item);
}
}
and I wanted to implement a listener on that list in another object:
class listenerClass extends PolymerElement {
Test get _data => $['Object'];
}
So the object is retrieved from the dom withthe getter.
Is there a way to observe a change in the parent? I tried the following:
#Observe("_data.list")
dataListChanged(_,__){
var item = _data.list.last;
//do magic with item.
}
I have the underscore because it is private and isnt exposed to Dom or anything... but the list itself isnt a property so it doesnt notify or anything.
I was hoping there was a way to do some sort of listener for it though.
My desired endstate is that I want to fire a function in the parent whenever an item is added to the list, with only the reference to the child object as defined above. Even though this _data is populated by way of Polymer, Since this isnt touching properties at all, the answer may likely just be Pure dart.
This is not how polymer works. Polymer framework has no way to know you have defined a getter in your class and emit the right notification.
You should add notify to the list property of Test and bind that to a property in listenerClass. Then observe that variable.
But probably you will have better luck with ObservableList and using autonotify for a simpler way to use observability with polymer-dart projects.

How to bind data in View

Actually someone asked me this question and I'm also interested to know, that how to bind data to a UI element directly. I know UITableview have Datasource property but it doesn't bind data directly. We have to use its protocol methods to bind data in code.
Is there any other way from which we can bind data to the View or is this possible or not? In .Net gridview we can bind data from database to gridview directly.
Update: If you mean synchronizing backing data with UI elements then read the last paragraph.
It would be against the recommended MVC pattern to bind data directly to the view if I understand your question correctly. Check the below links for more info.
Why MVC?
[Why MVC instead of good old ASP.NET? Still not grasping why I should go this route?][2]
However if you do want to bind data directly, there is nothing stopping you from it, even though it might be a bad idea unless the use case is trivial. For e.g. UITableViews are available with static cells. And if a pre-built UI element doesn't have a provision to bind data (don't know of any) to it directly, you could make a similar UI element that serves the purpose.
However it would take way more effort to build such and element than to supply data to it the existing one through preferred methods.
By binding data directly, if you mean supplying the data through interface builder, then you are out of luck. In Cocoa (for OS X application development), there is something called Bindings that help you synchronize your UI elements with the backing data. However in iOS there isn't such a thing. But you could use Key - Value - Observing to achieve this to some extent.
Also why iOS might not have such bindings may be partially answered here:
Is there any technical/conceptual reason why iOS does not support Cocoa Bindings?.
And check this if you have a need on such functionality: Is there any data binding mechanism available for iOS?
While it isn't exactly binding, I have used didSet property observers to update UI elements like this:
var label: UILabel?
var labelText = "Change me." {
didSet {
label?.text = labelText
}
}
That assumes you have initialized label somewhere appropriately. I believe that is the closest you can get in iOS.

Access Dart / Polymer WebComponent from main

Think of the following:
I've got a table data grid webcomponent and another component providing a data feed. In the applications main acting as kind of controller, i'd like to wire and setup those two components. Therefore i need a reference to underlying table grid instance Dart class and call methods on the "Component API' (to provide the table grid's tablemodel with data).
How do I access the Dart Class instance of a webcomponent instance from outside ?
Probably I missed something fundamental or are polymer webcomponents meant to interact only using databinding and stringy attributes stuff ?
Follow up: Found it !!
RLTable table = querySelector("#apptable").xtag;
does the job
As zoechi pointed out, xtag is not necessary.
var component = $['myComp'];
var componentXtag = $['myComp'].xtag;
print(component == componentXtag);
prints true. Therefore both
component.method()
componentXtag.method()
work fine
You don't need xtag. Some weeks/months ago this was a workaround until the final solution was landed.

What does [Bindable] mean in actionscript?

[Bindable]
/**
* Display output of video device.
*/
public var videoLocal : Video;
Anyone knows?
[Bindable] is a one of several meta tags that you can use in flex ActionScript code. It can be applied to properties, or methods that are marked in any scope. It cannot be used with static class members.
The key to using the [Bindable] meta tag is understanding what is going on under the hood when you use it. Essentially using data binding is a type of shorthand for adding event listeners and dispatching events.
There are two basic forms of the [Bindable] tag. The first is just [Bindable] followed by a var/property declaration. The Second is [Bindable(event="eventname")] followed by either a var/property declaration, a function/method declaration or one half of a getter/setter declaration.
I'll explain the longer notation first since the other builds on the same concept but with even more shorthand.
When you use [Bindable(event="eventname")] you are essentially telling the compiler that this var/property/function/method (call this the instance member) is 'available' to be used as the source for data binding. You are also telling it that when the value of the instance member has been invalidated/changed and it needs to be re-read that the "eventname" event will be dispatched.
In this longer form this all you are doing. You the developer are responsible for actually dispatching the "eventname" event whenever the value needs to be updated in the binding subscribers.
The real efficiency of using data binding comes on the subscribing side. The typical notation you will see in MXML is value="{instance.propertyName}" When you use the notation { } you are telling the compiler to do the following:
Create an event listener that listens to the event named in the bindable meta tag
In that event listener re-read the instance.propertyName and update this value
If you use the shorter form [Bindable], and you add the tag before a property/var, the compiler fills in the blanks and adds some additional functionality to make the property bindable. Essentially you are telling the compiler "add the events and methods you need to make this property bindable"
Now the way to think of what the compiler will do under the hood is this.
make a private version of your var
create an "event" to trigger the binding
create a getter function with scope and name of your original var that returns the private verson of the var when called.
create a setter function with scope and name of your original var that sets the private version of the var when called AND dispatches the triggering event.
In essence the compiler will do much of the work for you.
[Bindable]
public var xyz
is equivalent to
private var _xyz:String;
[Bindable(event="updateXYZValue")]
public function get xyz():String{
return _xyz;
}
public function set xyz(newxyz:String):void{
_xyz = newxyz;
dispatchEvent(new Event("updateXYZValue"));
}
The only functional differences in these is that in the first instance;
you do not know the name of the event that will be dispatched to trigger the binding
there is no way to update the underlying value without triggering the data binding
This second example also demonstrates one special case of the [Bindable] meta tag. This is that when you are applying it to a getter/setter pair defined for the same variable name you need only apply it to one or the other, it will apply to both. Typically you should set it on the getter.
You can use either notation on a function/method however if you do not specify an event the binding will never be triggered so if you are trying to bind to a function you should alway specify an event. It is also possible to specify more than one triggering event by stacking the tag. eg.
[Bindable(event="metaDataChanged")]
[Bindable(event="metaObjectUpdated")]
public function readMyMetaData():MetaDataObject{
var myMetaDataObject:MetaDataObject;
.
.
.
return myMetaDataObject;
}
This would presume that somewhere else you your class you will dispatch this metaDataChanged event or the metaObjectUpdated event when you want trigger the binding.
Also note that with this notation you can tie the binding of any instance member to any event that the instance will dispatch. Even inherited events that you yourself do not generate such as FrameEnter, OnChange, etc...
Data bindings can also be setup and destroyed during runtime. If you are interested in this take a look at the mx.binding.utils classes.
It is used in Databinding with Flex, you can read more about it here
http://livedocs.adobe.com/flex/3/html/help.html?content=databinding_2.html
Creating properties to use as the source for data binding
When you create a property that you
want to use as the source of a data
binding expression, Flex can
automatically copy the value of the
source property to any destination
property when the source property
changes. To signal to Flex to perform
the copy, you must use the [Bindable]
data tag to register the property with
Flex.
As an addition to what Justin said, you can actually use two ways data binding in Flex with the # character. Here's an example:
<s:TextInput id="txt1" text="#{txt2.text}" />
For a working example with source code enabled you can check out this article I wrote a while back:
Two-ways data binding in Flex

Resources