最近想要在 UI component 出現 / 消失的時候自動做一些事情,於是打算從 GXT Component
下手。不過怎麼寫怎麼有問題,只好寫 n 個 SSCCE 來確認一下,實驗結果紀錄於此。
基本認識
我關心這四個 method:
onLoad()
onUnload()
onShow()
onHide()
onLoad()
跟 onUnload()
是從 GWT 的 Widget
就定義的 method。理論上跟 onAttach()
、onDetach()
等意,就是這個 component 加入到 DOM(或是從 DOM 中移除)時會觸發的 method。不過 API 都強烈建議用 onLoad()
跟 onUnload()
了,就乖乖照辦。
onShow()
、onHide()
是 GXT Component 開始定義的 method,最常遇到的 caller 大概是 GXT Component 的 setVisible()
(override UIObject
)。
測試環境
- JDK 1.7
- GWT 2.7
- GXT 3.1.0
- Windows 7 (64bit)
- Chrome 50
測試方式
我製造了兩個 component FooButton
(繼承 TextButton
) 跟 FooCP
(繼承 ContentPanel
)。分別 override 上述四個 method,例如:
@Override
protected void onLoad() {
super.onLoad();
Console.log("load " + getText());
}
會需要 FooCP
是因為 AccordionLayoutContainer
跟 BorderLayoutContainer
(在某些情況下)要求 child 是 ContentPanel
。
基本上我是用 UiBinder 撰寫 TestLayout
(btw… TestLayout
繼承的是 GXT 的 Composite
),然後 entry point 的 onModuleLoad()
這樣寫:
Viewport vp = new Viewport();
vp.add(new TestLayout());
RootPanel.get().add(vp);
主要就是測試 FooButton
跟 FooCP
作為各 layout container 還有 GXT TabPanel
(見一次 murmur 一次,為啥這東西不是 container… ==”)的 child 時,上述四個 method 是否會觸發。
component 的行為(例如 collapse、close tab…)都是實際 UI 操作而不是程式呼叫 method。(希望這個差異不會炸出什麼新的問題)。
測試結果
注意:沒有測試所有已知的 layout container。
毫無反應區
下列 container 只會觸發 onLoad()
,不會觸發 onShow()
:
- AccordionLayoutContainer
- CenterLayoutContainer
- ContentPanel
- FieldLabel
- FieldSet(有設定
collapsible=true
) - FlowLayout
- HBoxLayoutContainer
- HorizontalLayoutContainer
- NorthSouthContainer
- SimpleContainer
- VBoxLayoutContainer
- VerticallayoutContainer
BorderLayoutContainer
center 的 child 只會在初始時觸發一次 onLoad()
,其餘操作均無反應。
其他四個 region 在初始時會先依序觸發 onLoad()
,然後再依序觸發 onShow()
… 三次(如果不是用 UiBinder,而是用 Swing 的方式直接掛一個組好的 BorderLayoutContainer
到 Viewport
,就會變兩次….. WTF?)
當某個 region 被 collapse 時,該 component 會觸發 onUnload()
、但是不會觸發 onHide()
。接著,其他還顯示的 region 會依序觸發 onShow()
。
當某個已經 collapse 的 region 展開回原狀時,會先觸發它的 onLoad()
,然後再依序呼叫全部 region 的 onShow()
。
當某個已經 collapse 的 region 以 float 的方式出現 / 消失時,會觸發 onLoad()
/ onHide()
,但是不會觸發其他 region 的 method。
當某個已經 collapse 的 region 以 float 的方式出現,然後再按下展開回原狀的按鈕,看起來是:
- 做 float region 消失的程序
- 做 region 恢復的程序
感覺有優化的空間
CardLayout
一開始會觸發所有 child 的 onHide()
,然後才觸發 onLoad()
,最後才是觸發 active widget 的 onShow()
。
切換 active widget 時,就是觸發對應 child 的 onShow
、onHide
。
TabPanel
(再 murmur 一次,為啥這玩意不是 layout container ==”)
初始時的觸發順序
- active widget 的
onHide()
- active widget 的
onShow()
- 其他 child 的
onHide()
- 全部 child 的
onLoad()
以下假設目前的 active widget 是 Foo1
,另外還有一個 Foo2
。
- 將 active widget 切換為
Foo2
:- 觸發
Foo1
的onHide()
- 觸發
Foo2
的onShow()
- 觸發
- 關掉有
Foo2
的 tab:- 觸發
Foo2
的onUnload()
- 觸發
Foo2
的onShow()
- 觸發
- 關掉有
Foo1
的 tab:- 觸發
Foo1
的onUnload()
- 觸發
Foo1
的onShow()
- 觸發
Foo2
的onShow()
- 觸發
簡單地說,被關掉的 child 都會先觸發 onUnload()
然後再觸發 onShow()
(WTF?)
結論(X) 詰譙(O)
其實不知道要有什麼結論… Orz
AccordionLayoutContainer
跟 FieldSet
並不會觸發 onShow()
/ onHide()
,這點還可以接受。
CardLayoutContainer
的初始化步驟非常怪,都還沒掛上 DOM 那觸發 onHide()
是要幹麼?但是初始化只有一次,所以就算了。
BorderLayoutContainer
的 collapse 行為跟 onHide()
一點關係也沒有,但是會觸發其他 region 的 onShow()
?
TabPanel
可能是集各種詭異於一身的… 對,他還不是 container(謎之聲:你是要講幾次?)。關掉一個 tab 會觸發 onUnload()
這完全合情合理,但是為什麼還會再觸發 onShow()
阿阿阿阿…… Orz
我很願意相信,這背後都有好理由來支撐這一堆詭異行為;只是我更希望能有統一的行為模式,雖然會關心到這種 detail 程度的時候好像不多…
可是我就需要阿... [淚目]
這看起來要 trace javascript code 才能看到全貌
回覆刪除不用耶... 因為基本上都已經包成 Java 的樣子了
回覆刪除