3.5.3.1.2. 集合容器
CollectionContainer
接口用来容纳相同类型实例的集合。这个接口是 InstanceContainer
的后代,定义了以下特有的方法:
setItems()
- 为容器设置实体集合。getItems()
- 返回容器中保存的实体的不可变列表。可以用这个方法来遍历集合、获得实体集合流或者用根据索引获取单一实例。如果需要按照实体的 id 获取实例,使用getItem(entityId)
方法。示例:
@Inject
private CollectionContainer<Customer> customersDc;
private Optional<Customer> findByName(String name) {
return customersDc.getItems().stream()
.filter(customer -> Objects.equals(customer.getName(), name))
.findFirst();
}
getMutableItems()
- 返回容器中保存的实体的可变列表。所有对列表的改动,包括add()
、addAll()
、remove()
、removeAll()
、set()
、clear()
方法都会产生CollectionChangeEvent
事件,所以订阅了这个事件的可视化组件也会根据变化更新,示例:
@Inject
private CollectionContainer<Customer> customersDc;
private void createCustomer() {
Customer customer = metadata.create(Customer.class);
customer.setName("Homer Simpson");
customersDc.getMutableItems().add(customer);
}
只有在需要更改集合的时候使用 getMutableItems()
,否则应该使用 getItems()
,防止意外改动。
setItem()
- 为容器设置 当前 实例。如果提供的内容不是 null,则必须是集合中的一个对象。此方法会发送ItemChangeEvent
。
需要注意的是,类似 Table 的可视化组件不会监听容器发送的 ItemChangeEvent
事件。所以如果需要在表中选中一行,需要使用集合容器的 setSelected()
方法,而不是 setItem()
。容器的当前 item 也会更改,因为容器同时也监听了组件。示例:
@Inject
private CollectionContainer<Customer> customersDc;
@Inject
private GroupTable<Customer> customersTable;
private void selectFirstRow() {
customersTable.setSelected(customersDc.getItems().get(0));
}
getItem()
- 重写了InstanceContainer
的同名方法,返回 当前 实例。如果当前实例没有设置,此方法会抛出一个异常。所以需要在确保容器有选中当前实例的时候才使用此方法,然后就不需要检查返回值是否为 null。getItemOrNull()
- 重写了InstanceContainer
的同名方法,返回 当前 实例。如果当前实例没有设置,此方法会返回 null。所以在使用此方法返回值之前总是需要先检查返回的是否是 null。getItemIndex(entityId)
- 返回实例在getItems()
和getMutableItems()
方法返回的列表中的位置。此方法接收Object
对象,因此可以传给它 id 或者实体实例本身。容器的实现维护了一个 id 到索引的映射,所以这个方法即使在非常大的列表中也有很高效率。getItem(entityId)
- 按照实例的 id 返回此实例。这个是一个快捷方法,首先用getItemIndex(entityId)
得到实例的位置,然后通过getItems().get(index)
返回实例。所以如果需要找的实例不在集合中存在,则会抛出异常。getItemOrNull(entityId)
- 跟getItem(entityId)
类似,只不过在实例不存在的时候会返回 null。所以需要在使用前检查此方法的返回值是否是 null。containsItem(entityId)
- 如果指定 id 的实体在集合中存在的话,返回 true。底层其实调用了getItemIndex(entityId)
方法。replaceItem(entity)
- 如果在容器中有相同 id 的实例,则会被方法的输入参数的实例替换。如果不存在,则会添加新的实例到实例列表中。此方法会发送CollectionChangeEvent
事件,根据具体做了什么,事件类型可以是SET_ITEM
或者ADD_ITEMS
。setSorter()
- 设置此容器的排序器。Sorter
接口的标准实现是CollectionContainerSorter
。当容器关联到加载器时,会设置默认的排序器。也可提供自定义的实现。getSorter()
- 返回此容器当前设置的排序器。
- CollectionContainer 事件
除了 InstanceContainer 的事件之外,还可以使用CollectionContainer
接口注册CollectionChangeEvent
事件的监听器,该事件在容器内的实体集合改动时发送,比如,添加、删除和替换集合内元素。下面例子展示了订阅容器的事件,该容器在界面 XML 中使用customersDc
id定义:@Subscribe(id = "customersDc", target = Target.DATA_CONTAINER)
private void onCustomersDcCollectionChange(
CollectionContainer.CollectionChangeEvent<Customer> event) {
CollectionChangeType changeType = event.getChangeType(); (1)
Collection<? extends Customer> changes = event.getChanges(); (2)
// …
}
1 - 改动类型:REFRESH,ADD_ITEMS,REMOVE_ITEMS,SET_ITEM。 2 - 从容器中添加或者删除的实体集合。如果改动类型是 REFRESH,框架不能确定具体是哪些实体添加或者删除,所以此时该集合为空。