从最初的一千个成员加入了社区开始,我们就认识到对于“标准” CRUD 界面的需求是有多么广泛,已经超出了最开始我们设计的一组功能了。然而,很长一段时间,即使没有 API 层,我们也能够处理自定义行为的需求,这是因为有另一个第一阶段假设 - 开放继承。有效地进行开放继承意味着可以覆盖基础类的任何公共或保护方法,再根据需要定制其行为。这听起来似乎是所有顽疾的解药,但事实上可能短期都不一定能见效:如果被覆盖的方法被重命名、删除了或者将来版本的框架根本不同这个方法了,该怎么办?
所以,为了响应社区日益增长的需求,我们决定引入新的界面API。API提供了清晰的长期的扩展点,而没有隐藏的声明式暗喻,灵活并且易于使用。
界面声明在 CUBA 7 里,界面声明异常简单:
从上面的例子我们可以看到,界面的标识符在控制器类上显式的进行定义。也就是说,现在界面id和控制器类能相互唯一的对应。由此带来的好消息就是,现在界面可以直接通过其控制类来安全访问了(注意下面例子用控制器类来创建确认窗口):
至此,界面描述文件不再是必须的,而成为了一个补充的部分。界面布局可以通过编程的方式创建或者通过 XML 界面描述声明式创建,界面描述通过控制器类的 @UiDescriptor 注解定义。这样能使得控制器和布局更加容易读懂。这个方式跟Android开发中使用的模式非常类似。
之前,需要在web-screens.xml中注册一个界面描述并为其设置一个标识符。在 CUBA 7 中,这个文件只是因为兼容性的考虑被保留下来,用新方法创建界面不需要这种注册了。
界面生命周期新的API带来了清晰的自描述的界面生命周期事件:
l Init
l AfterInit
l BeforeShow
l AfterShow
l BeforeClose
l AfterClose
CUBA 7 中所有的界面相关的事件都可以用下面的方式订阅:
将新API与旧方法进行比较,可以看到我们没有重写钩子方法,之前这些钩子方法在父类的层次结构中被模糊地调用。现在我们在界面生命周期的明确预定义的点中定义业务逻辑。
事件处理和功能代理前一小节我们介绍了如何订阅生命周期事件,那么,其他组件呢?我们是否应该像在6.x版本中那样在界面初始化时分散所有必需的监听器?新API非常统一,因此订阅其他事件与生命周期事件完全相似。
我们举一个带有两个UI元素的简单例子,一个按钮和一个货币字段控件,因此它的XML描述符如下所示:
通过单击按钮我们调用中间件服务返回一个数字,该数字将被写到货币控件中。货币控件需要根据价格的值更改其样式。
在上面的例子中,我们看到有两个事件处理器:一个是按钮按下时调用的,另一个是当货币控件的值发生变化时执行的。就是这么简单。
现在,我们设想一下,如果需要验证价格的值并确保其为一个正数。最直接的方法就是在界面初始化的时候为其添加一个验证器: