ScreenFragment 事件

本节介绍界面 fragment 控制器能处理的生命周期事件。

InitEvent

该事件在 fragment 控制器和其所有以声明方式定义的组件创建之后,并且依赖注入完成才触发。此时,内部的 fragment 还没有初始化。有些可视化组件没有完全初始化,比如按钮还没有连接到操作。如果该 fragment 是通过 XML 的方式绑定到宿主界面的话,该事件会在宿主控制器的 InitEvent 事件之后触发。否则会在该 fragment 被添加到宿主组件树的时候触发。

AfterInitEvent

该事件会在 fragment 控制器和其所有以声明方式定义的组件创建之后,并且依赖注入完成,所有组件内部的初始化过程也已经结束之后触发。此时,内部的界面 fragment(如果有的话)已经触发了它们自己的 InitEventAfterInitEvent 事件。在该事件的监听器中,可以创建可视化和数据组件,并能执行依赖内部 fragment 初始化完成的额外初始化过程。

AttachEvent

该事件会在 fragment 被添加到宿主的组件树时触发,fragment 已经完全初始化了,InitEventAfterInitEvent 事件已经触发。在该事件的监听器中,可以通过 getHostScreen()getHostController() 访问宿主界面的界面和方法。

监听 AttachEvent 事件的示例:

@UiController("sample_AddressFragment")
@UiDescriptor("address-fragment.xml")
public class AddressFragment extends ScreenFragment {
    private static final Logger log = LoggerFactory.getLogger(AddressFragment.class);

    @Subscribe
    private void onAttach(AttachEvent event) {
        Screen hostScreen = getHostScreen();
        FrameOwner hostController = getHostController();
        log.info("onAttach to screen {} with controller {}", hostScreen, hostController);
    }

DetachEvent

该事件会在 fragment 以编程的方式从宿主的组件树中移除时触发。在该事件监听器中也能访问宿主界面。

监听宿主界面事件

在 fragment 控制器中,可以订阅父界面的事件,需要在注解中为 target 属性指定 PARENT_CONTROLLER 值,示例:

@Subscribe(target = Target.PARENT_CONTROLLER)
private void onBeforeShowHost(Screen.BeforeShowEvent event) {
    // ...
}

这个方法可以处理任何事件,包括实体编辑界面发送的 InitEntityEvent 事件。

在宿主界面监听 Fragment 事件

在宿主界面控制器中,可以订阅 fragment 控制器发送的事件。下面示例中,当 fragment 组件更改时发送自定义事件,并在宿主界面处理。

在 fragment 控制器中,创建事件类和一个方法用于注册事件监听器:

AddressFragment.java
public static class CountryChangeEvent extends EventObject { (1)

    private Country country;

    public CountryChangeEvent(Object source, Country value) {
        super(source);
        country = value;
    }

    public Country getCountry() {
        return country;
    }
}

public Subscription addChangeListener(Consumer<CountryChangeEvent> listener) {
    return getEventHub().subscribe(CountryChangeEvent.class, listener); (2)
}

@Subscribe("countryField")
public void onCountryFieldValueChange(HasValue.ValueChangeEvent<Country> event) {
    fireEvent(CountryChangeEvent.class, new CountryChangeEvent(this, event.getValue())); (3)
}
1 通过继承 EventObject 创建自定义事件类。
2 创建一个方法用于注册自定义事件监听器。
3 使用 fireEvent() 方法发送自定义事件。

现在可以在宿主控制器中以声明式的方法订阅自定义 fragment 事件:

HostScreen.java
@Autowired
private Notifications notifications;

@Subscribe(id = "addressFragment", target = Target.CONTROLLER) (1)
protected void onChange(AddressFragment.CountryChangeEvent event) {
    notifications.create()
            .withCaption("Changed country: " + event.getCountry())
            .show();
}
1 使用 fragment id 和 Target.CONTROLLER 订阅 fragment 事件。