javafx阴影_JavaFX技巧来节省内存! 属性和可观察对象的阴影场
javafx陰影
在 JavaFX的世界中, Properties API允許UI開發(fā)人員將值綁定到UI控件。 這種功能出奇的簡(jiǎn)單,但是當(dāng)對(duì)象模型經(jīng)常使用屬性時(shí),應(yīng)用程序可能會(huì)很快耗盡內(nèi)存。 我通常會(huì)編寫兩個(gè)單獨(dú)的對(duì)象,例如pojo類和表示模型對(duì)象。 此技術(shù)通常在基于Swing的應(yīng)用程序中使用。 從JavaFX角度來看,您可以只創(chuàng)建一個(gè)具有屬性的對(duì)象,以允許觀察者(偵聽器)更新值。 聽起來不錯(cuò)吧? 不完全是因?yàn)橹饕獑栴}是當(dāng)所有對(duì)象的(pojo)屬性(字段)都是還包裝實(shí)際值的屬性時(shí),程序員(api的用戶)可能根本不想綁定或使用屬性,而只想訪問實(shí)際值。 那么,JavaFX開發(fā)人員該做什么?
一個(gè)TreeTable控件持有雇員。
我經(jīng)常訪問Dirk Lemmermann的博客Pixel Perfect ,該博客經(jīng)常發(fā)布非常有用的JavaFX技巧。 最近,Dirk在博客中發(fā)布了有關(guān)如何使用名為Shadow Fields的有趣模式來節(jié)省內(nèi)存的信息。 要查看他的帖子,請(qǐng)?jiān)L問他的博客條目JavaFX Tip 23:節(jié)省內(nèi)存! 屬性的陰影字段。 。 Dirk的JavaFX技巧確實(shí)有助于解決上述問題(減少堆),但是我注意到必須存在樣板代碼才能( 聰明地 確定 )為調(diào)用者提供返回值是實(shí)際對(duì)象還是屬性包裝器對(duì)象。 例如,該代碼將返回int或Integer值,而不是在調(diào)用get或set方法時(shí)返回IntegerProperty對(duì)象,從而節(jié)省了內(nèi)存。 此外,代碼聲明了兩個(gè)變量來保存兩種值類型之一。 例如:
private String _title = "Untitled"; // shadow field private StringProperty title;我覺得我可以使事情更簡(jiǎn)潔,并可能節(jié)省更多的內(nèi)存。 并減少樣板代碼。 我決定使用Java 8的默認(rèn)方法創(chuàng)建一個(gè)接口,該接口將處理管理實(shí)際值和屬性。 API的用戶將只創(chuàng)建一個(gè)實(shí)現(xiàn)以下接口的域類:
界面屬性訪問器
一個(gè)提供訪問器方法的接口,以提供對(duì)實(shí)際對(duì)象值或JavaFX屬性包裝器對(duì)象的智能確定。 API的用戶必須實(shí)現(xiàn)一種稱為getModelProperties()的方法,該方法返回屬性名(字符串)和值(對(duì)象)的映射。 該值可以是實(shí)際對(duì)象或?qū)傩灶愋蛯?duì)象。 下面的代碼也將支持可觀察列表。
package com.jfxbe;import javafx.beans.property.Property; import javafx.collections.FXCollections; import javafx.collections.ObservableList;import java.lang.reflect.Constructor; import java.util.ArrayList; import java.util.List; import java.util.Map;/*** Provide default methods to support the similar* capability of the shadow fields pattern.* To save memory object values don't have to be* wrapped into a Property object when using getters* and setters, however when calling property type methods* values will be wrapped into a property object.** Default methods for Observable lists are provided too.** Created by cpdea on 4/3/16.*/ public interface PropertyAccessors {Map<String, Object> getModelProperties();default <T> T getValue(String name, Object defaultVal) {Object p = getModelProperties().get(name);p = p==null ? defaultVal : p;return (T) ((p instanceof Property) ? ((Property) p).getValue(): p);}default void setValue(String name, Object value) {Object p = getModelProperties().get(name);if (p instanceof Property) {((Property)p).setValue(value);} else {getModelProperties().put(name, value);}}default <T> T refProperty(String name, Class propClass, Class rawValType) {Object p = getModelProperties().get(name);Property prop = null;try {if (p == null) {Class[] constructorTypes =new Class[]{Object.class, String.class};Constructor<Property> propConstr =propClass.getDeclaredConstructor(constructorTypes);prop = propConstr.newInstance(this, name);} else if (rawValType.isInstance(p)) {Class[] constructorTypes = new Class[]{Object.class,String.class, rawValType};Constructor<Property> propConstr =propClass.getDeclaredConstructor(constructorTypes);prop = propConstr.newInstance(this, name, p);} else {prop = (Property) p;}getModelProperties().put(name, prop);} catch (Exception e) {e.printStackTrace();}return (T) prop;}default <T> List<T> getValues(String name, List<T> defaultValue) {Object p, o = getModelProperties().get(name);p = o;o = o==null ? defaultValue : o;if (!o.equals(p)) {getModelProperties().put(name, o);}return (List<T>) o;}default <T> void setValues(String name, List<T> newList) {Object list = getModelProperties().get(name);if (list == null || !(list instanceof ObservableList)) {getModelProperties().put(name, newList);} else {// Should the list be totally replaced? below clears and adds all itemsObservableList<T> observableList = (ObservableList<T>) list;observableList.clear();observableList.addAll(newList);}}default <T> ObservableList<T> refObservables(String name) {List list = (List) getModelProperties().get(name);if (list == null) {list = FXCollections.observableArrayList(getValues(name, new ArrayList<>()));getModelProperties().put(name, list);}if (! (list instanceof ObservableList)) {list = FXCollections.observableArrayList(list);getModelProperties().put(name, list);}return (ObservableList<T>) list;} }員工階層
一個(gè)名為Employee的類,它實(shí)現(xiàn)PropertyAccessor接口。 在下面,您會(huì)注意到每個(gè)字段的屬性名稱都是使用public static final String聲明的 。 例如,員工的名字是:
public static final String NAME_PROPERTY = “name”;對(duì)于諸如getter,setter和xyzProperty()之類的訪問器方法,您會(huì)在PropertyAccessor接口中注意到對(duì)默認(rèn)方法的調(diào)用。
package com.jfxbe;import javafx.beans.property.ObjectProperty; import javafx.beans.property.SimpleStringProperty; import javafx.beans.property.StringProperty; import javafx.collections.ObservableList;import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map;/*** A hybrid domain and model object using the shadow field pattern to save memory.* Created by cpdea*/ public class Employee implements PropertyAccessors{/** This is a map to hold properties and observables */private Map<String, Object> modelProperties;public static final String NAME_PROPERTY = "name";public static final String POWERS_PROPERTY = "powers";public static final String SUPERVISOR_PROPERTY = "supervisor";public static final String MINIONS_PROPERTY = "minions";public Employee(String name, String powers) {setName(name);setPowers(powers);}@Overridepublic Map<String, Object> getModelProperties() {if (modelProperties == null) {modelProperties = new HashMap<>();}return modelProperties;}public final String getName() {return getValue(NAME_PROPERTY, "");}public final void setName(String name) {setValue(NAME_PROPERTY, name);}public final StringProperty nameProperty() {return refProperty(NAME_PROPERTY, SimpleStringProperty.class, String.class);}public String getPowers() {return getValue(POWERS_PROPERTY, "");}public final StringProperty powersProperty() {return refProperty(POWERS_PROPERTY, StringProperty.class, String.class);}public final void setPowers(String powers) {setValue(POWERS_PROPERTY, powers);}public final Employee getSupervisor() {return getValue(SUPERVISOR_PROPERTY, null);}public final ObjectProperty<Employee> supervisorProperty() {return refProperty(SUPERVISOR_PROPERTY, ObjectProperty.class, Employee.class);}public final void setSupervisor(Employee supervisor) {setValue(SUPERVISOR_PROPERTY, supervisor);}public final List<Employee> getMinions() {return getValues(MINIONS_PROPERTY, new ArrayList<>());}public final ObservableList<Employee> minionsObservables() {return refObservables(MINIONS_PROPERTY);}public final void setMinions(List<Employee> minions) {setValues(MINIONS_PROPERTY, minions);}}結(jié)論
因此,您已找到解決方案,嘗試消除兩個(gè)變量和其他樣板代碼。 我實(shí)際上并沒有使用大量數(shù)據(jù)來測(cè)試代碼,因此也許在另一篇文章中或某個(gè)幸運(yùn)的讀者會(huì)創(chuàng)建一個(gè)測(cè)試,以比較所有三個(gè)(對(duì)象具有所有屬性,Dirk和mine的)實(shí)現(xiàn)。
與RMI服務(wù)器一起使用時(shí),此方法的可能缺點(diǎn)可能是序列化對(duì)象。 我敢肯定還有其他可能的缺點(diǎn),但是對(duì)于大多數(shù)用例而言,這可能更容易處理和更簡(jiǎn)潔。
請(qǐng)隨意發(fā)表評(píng)論!
參考資料
- https://dlemmermann.wordpress.com
- https://docs.oracle.com/javase/8/javafx/api/javafx/beans/property/Property.html
- http://blog.netopyr.com/2011/05/13/javafx-properties/
- https://projectlombok.org
- http://www.jgoodies.com/freeware/libraries/binding
翻譯自: https://www.javacodegeeks.com/2016/04/javafx-tips-save-memory-shadow-fields-properties-observables.html
javafx陰影
總結(jié)
以上是生活随笔為你收集整理的javafx阴影_JavaFX技巧来节省内存! 属性和可观察对象的阴影场的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 神曲安卓版下载(神曲安卓)
- 下一篇: openshift_Openshift源