javafx阴影_JavaFX技巧来节省内存! 属性和可观察对象的阴影场

javafx阴影

JavaFX的世界中, Properties API允许UI开发人员将值绑定到UI控件。 这种功能出奇的简单,但是当对象模型经常使用属性时,应用程序可能会很快耗尽内存。 我通常会编写两个单独的对象,例如pojo类和表示模型对象。 此技术通常在基于Swing的应用程序中使用。 从JavaFX角度来看,您可以只创建一个具有属性的对象,以允许观察者(侦听器)更新值。 听起来不错吧? 不完全是因为主要问题是当所有对象的(pojo)属性(字段)都是还包装实际值的属性时,程序员(api的用户)可能根本不想绑定或使用属性,而只想访问实际值。 那么,JavaFX开发人员该做什么?

一个TreeTable控件持有雇员。

一个TreeTable控件持有雇员。

我经常访问Dirk Lemmermann的博客Pixel Perfect ,该博客经常发布非常有用的JavaFX技巧。 最近,Dirk在博客中发布了有关如何使用名为Shadow Fields的有趣模式来节省内存的信息。 要查看他的帖子,请访问他的博客条目JavaFX Tip 23:节省内存! 属性的阴影字段。 。 Dirk的JavaFX技巧确实有助于解决上述问题(减少堆),但是我注意到必须存在样板代码才能( 聪明地 确定 )为调用者提供返回值是实际对象还是属性包装器对象。 例如,该代码将返回intInteger值,而不是在调用getset方法时返回IntegerProperty对象,从而节省了内存。 此外,代码声明了两个变量来保存两种值类型之一。 例如:

private String _title = "Untitled"; // shadow field
private StringProperty title;

我觉得我可以使事情更简洁,并可能节省更多的内存。 并减少样板代码。 我决定使用Java 8的默认方法创建一个接口,该接口将处理管理实际值和属性。 API的用户将只创建一个实现以下接口的域类:

界面属性访问器

一个提供访问器方法的接口,以提供对实际对象值或JavaFX属性包装器对象的智能确定。 API的用户必须实现一种称为getModelProperties()的方法,该方法返回属性名(字符串)和值(对象)的映射。 该值可以是实际对象或属性类型对象。 下面的代码也将支持可观察列表。

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;}
}

员工阶层

一个名为Employee的类,它实现PropertyAccessor接口。 在下面,您会注意到每个字段的属性名称都是使用public static final String声明的 。 例如,员工的名字是:

public static final String NAME_PROPERTY = “name”;

对于诸如getter,setter和xyzProperty()之类的访问器方法,您会在PropertyAccessor接口中注意到对默认方法的调用。

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);}}

结论

因此,您已找到解决方案,尝试消除两个变量和其他样板代码。 我实际上并没有使用大量数据来测试代码,因此也许在另一篇文章中或某个幸运的读者会创建一个测试,以比较所有三个(对象具有所有属性,Dirk和mine的)实现。

与RMI服务器一起使用时,此方法的可能缺点可能是序列化对象。 我敢肯定还有其他可能的缺点,但是对于大多数用例而言,这可能更容易处理和更简洁。

请随意发表评论!

参考资料

  • 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阴影

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/336133.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

yum install -y 是什么意思_为什么你应该在docker 中使用gosu?

为什么要使用gosu&#xff1f;Docker容器中运行的进程&#xff0c;如果以root身份运行话会有安全隐患&#xff0c;该进程拥有容器内的全部权限&#xff0c;更可怕的是如果有数据卷映射到宿主机&#xff0c;那么通过该容器就能操作宿主机的文件夹了&#xff0c;一旦该容器的进程…

openshift_Openshift源中的高可用性Drools无状态服务

openshift嗨&#xff0c;大家好&#xff01; 在这篇博客文章中&#xff0c;我想举一个简单的示例&#xff0c;展示使用Openshift 3&#xff08;Docker和Kubernetes&#xff09;扩展我们的Drools Stateless服务有多么容易。 我将展示如何通过按需提供新实例来扩展我们的服务&…

ibm服务器芯片架构,IBM x366 服务器技术详解

背景资料IBM eServer x366 提供了突破性的 4 路性能&#xff0c;采用机架优化的 3U服务器设计&#xff0c;结合了源自大型机灵感的 eServer X3技术的高可用性&#xff0c;具有最新 64 位Intel Xeon MP 处理器带来的 64位性能&#xff0c;可创建面向商业企业应用程序、虚拟化及 …

python antlr_使用ANTLR在5分钟内用Java解析任何语言:例如Python

python antlr我喜欢出于多种目的处理代码&#xff0c;例如静态分析或自动重构。 对我来说&#xff0c;有趣的部分是推理从抽象语法树&#xff08;AST&#xff09;构建的模型。 为此&#xff0c;您需要一种从源文件中获取AST的方法。 可以使用ANTLR轻松完成此操作&#xff0c;并…

rostcm6情感分析案例分析_卷积情感分析

这是一个面向小白(比如&#xff0c;本人)的关于情感分析的系列教程 [1]。老鸽子整理了“4 - Convolutional Sentiment Analysis.ipynb”中的内容。本文任务&#xff1a;使用卷积神经网络(CNN)来实现句子分类。简介CNN用于分析图像&#xff0c;包含一个或多个卷积层&#xff0c;…

java jigsaw_60秒内使用Java 9的Project Jigsaw的JavaFX HelloWorld

java jigsaw到目前为止&#xff0c;您可能已经听说过Java 9的新模块系统&#xff0c;即项目Jigsaw。 如果您不了解Java 9的新模块系统&#xff0c;则应该访问Mark Reinhold的论文“模块系统的状态” 。 另外&#xff0c;您应该在nipafx上查看 Nicolai Parlog的优秀博客&#xf…

opencv python 多帧降噪算法_OpenCV-Python中用于视频跟踪的Meanshift和Camshift算法介绍...

学习目标在本章中&#xff0c;我们将学习用于跟踪视频中对象的Meanshift和Camshift算法。MeanshiftMeanshift背后的直觉很简单&#xff0c;假设你有点的集合。(它可以是像素分布&#xff0c;例如直方图反投影)。你会得到一个小窗口(可能是一个圆形)&#xff0c;并且必须将该窗口…

vue.jsr入门_JSR-308和Checker框架为jOOQ 3.9添加了更多类型安全性

vue.jsr入门Java 8引入了JSR-308&#xff0c;它为Java语言添加了新的注释功能。 最重要的是&#xff1a;键入注释。 现在可以像下面这样设计怪物了&#xff1a; 比注解更疯狂的是类型注解。 在数组上。 谁认为这是有效的Java代码&#xff1f; pic.twitter.com/M9fSRRerAD — …

数组索引必须为正整数或逻辑值_Office 365函数新世界——动态数组

革新一个旧的函数体系&#xff0c;无外乎从这么几个方面入手&#xff0c;函数的运行效率、函数的编写方式以及扩展新的函数功能。今天咱们就学习一下&#xff0c;看看365新函数是如何通过这三个方面打破旧函数条条框框的。365函数系列推出了一个新的概念&#xff0c;叫做动态数…

【Android OpenGL ES 开发 (零)】创建一个新的工程

创建符合要求的AndroidApp 使用Android Studio开发&#xff0c;Android Studio下载地址 1.先创建Native C 2.项目相关添加 3.使用C11标准 学习使用JNI为Java提供API 1.在cpp中定义相关接口&#xff0c;格式如下 2.外部调用这个API 把so改成自己想要的名字 1.需要在cmake文件…

java方法参数类型不确定_一个Java方法能有多少个参数类型?这个好奇coder做了个实验...

选自 justinblank机器之心编译参与&#xff1a;李志伟、张倩在 JVM 中&#xff0c;一个 Java 方法&#xff0c;最多能定义多少参数呢&#xff1f;这是一个很无聊的问题&#xff0c;即使能定义一万个&#xff0c;十万个&#xff0c;谁又会真的去这么做呢。但是作为一个 coder&am…

lagom的微服务框架_您的第一个Lagom服务– Java Microservices入门

lagom的微服务框架在撰写我的下一份OReilly报告时&#xff0c;我一直很沮丧&#xff0c;并且一段时间内没有足够的时间来撰写博客。 是时候赶快来这里&#xff0c;让您真正快速地开始使用名为Lagom的新微服务框架。 它与您从Java EE或其他应用程序框架中可能了解到的有所不同。…

【Android OpenGL ES 开发 (一)】使用c++开发opengles 与 日志功能 及 加载assets

创建OpenGLES视口 1.App窗口改成OpenGL窗口,是通过java调用C&#xff0c;在以下位置修改如下内容 package com.example.learnogles;import androidx.appcompat.app.AppCompatActivity;import android.content.Context; import android.opengl.GLSurfaceView; import android.o…

水印相机定位不准确怎么办_禄来的广角双反相机(2020版)

点击上方胶卷迷俱乐部快速关注&#xff0c;胶卷迷们坚实的阵地内容主要原创&#xff0c;配图来自群友和网络&#xff0c;所有水印保留最下方为微信自带广告&#xff0c;支持请点击(本号可获微量收入)4.0德国禄来公司以双反相机名震天下&#xff0c;其中的2.8&#xff0c;3.5两个…

【Android OpenGL ES 开发 (二)】渲染管线与Shader

计算出每一帧耗费的时间 1.在头文件中加入time.h,cpp中实现如下计算时间接口 float GetFrameTime(){static unsigned long long lastTime0,currentTime0;timeval current;gettimeofday(&current, nullptr);//取当前时间currentTime current.tv_sec * 1000 current.tv…

【Android OpenGL ES 开发 (三)】Shader 扩展

编译Shader代码 1.封装一个编译shader的接口 GLuint CompileShader(GLenum shaderType,const char *shaderCode){GLuint shaderglCreateShader(shaderType);glShaderSource(shader,1,&shaderCode,NULL);glCompileShader(shader);GLint compileResultGL_TRUE;glGetShaderi…

css阴影属性_第三场阴影场与属性访问器接口

css阴影属性这是“ 影子字段与属性访问器”界面的 第3轮 。 如果您是新手&#xff0c;但不确定要怎么做&#xff0c;请查看我以前的文章或关于开发JavaFX应用程序时节省内存的第一篇文章 。 作为Java开发人员&#xff0c;我主要关心的是在开发JavaFX域模型时在性能 &#xff0c…

js if判断多个条件_JS条件判断小技巧(一)

经常code review&#xff0c;我发现JS newbie很容易写出一堆冗长的代码。今天就列几个比较常见的“解决之道”&#xff0c;看看如何减少JS里的条件判断。提前返回&#xff0c;少用if...else“if...else是编程语言的精华。——鲁迅”但是过多的嵌套&#xff0c;还是挺令人抓狂的…

【Android OpenGL ES 开发 (四)】纹理相关(一)

纹理贴图的原理 1.作用&#xff1a;可以用来渲染视频。 2.纹理坐标 生成OpenGL中的纹理对象 1.像素数据想要绘制出来需要先变成纹理 2.创建纹理放在GPU上 GLuint CreateTexture2D(unsigned char *pixelData,int width,int height,GLenum type) {GLuint texture;glGenTextu…

jmx 替代_使用JMX作为Ganglia的现代替代品进行CLDB监视

jmx 替代有许多选项可用于监视MapR集群的性能和运行状况。 在本文中&#xff0c;我将介绍使用Java管理扩展&#xff08;JMX&#xff09;监视CLDB的鲜为人知的方法。 据最受尊敬的MapR数据工程师之一&#xff0c;Akihiko Kusanagi称&#xff0c;与使用Ganglia相比&#xff0c;使…