Guice 4.0在這裏。我已經使用Guice幾年了,真的很喜歡它。我現在需要一個Swing應用程序,並且對如何設計Guice API來滿足Swing(恕我直言)怪異的需求/最佳實踐感到困惑。Guice和Swing的併發模型看起來不兼容
通常,當我使用吉斯,我有一個主要的「驅動器」類像MyApp
我絲吉斯像這樣:
// Groovy pseudo-code
class MyApp {
@Inject
FizzClient fizzClient
@Inject
BuzzClien buzzClient
static void main(String[] args) {
MyApp myapp = Guice.createInjector(new MyAppModule()).getInstance(MyApp)
myapp.run()
}
private void run() {
// Do whatever the app does...
}
}
class MyAppModule extends AbstractModule {
@Override
void configure() {
bind(FizzClient).to(DefaultFizzClient)
bind(BuzzClient).to(DefaultBuzzClient)
// etc...
}
}
但在擺動的情況下,JFrame
是的GUI應用程序,所以對我來說,是有意義的有MyApp
延長JFrame
:
class MyApp extends JFrame {
// etc...
}
的問題是,在搖擺,你需要做一些非常規的線程掛羊頭賣狗肉,使:
- 操縱的
JFrame
或的其他JComponents
的任何代碼的UI需要在事件調度線程(EDT)發生 - 這是通過完成SwingUtilities.invokeLater
;和 - 任何代碼,將阻塞並需要一段時間才能完成需要被轉移到了自己的
SwingWorker
螺紋
所以我們可以說我有一個需要熱身在應用程序啓動大緩存(或許這需要30-60秒)。這是我最好的嘗試迄今:
@Canonical // Creates a tuple constructor and a bunch of other stuff for me
@Slf4j
class MyApp extends JFrame {
@Inject
MyAppCache appCache
static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
@Override
void run() {
// The Guice-based bootstrapping has to happen inside invokeLater
// because MyApp *is* a JFrame (hence UI).
Guice.createInjector(new MyAppModule()).getInsance(MyApp).init()
}
})
}
void init() {
new SwingWorker<Void,String>() {
@Override
protected Void doInBackground() {
appCache.warmUp()
publish('Cached is warmed up!')
}
@Override
protected void process(List<String> updates) {
log.info(updates)
}
}.execute()
}
}
class MyAppModule extends AbstractModule {
@Override
void configure() {
bind(MyAppCache).to(DefaultAppCache)
}
@Provides
MyApp providesMyApp(MyAppCache appCache) {
MyApp app = new MyApp(appCache)
app.title = 'My App'
app.defaultCloseOperation = JFrame.EXIT_ON_CLOSE
app.pack()
// ...etc. (configure the parent JFrame)
}
}
當我運行這段代碼我上SwingWorker
內appCache.warmUp()
語句NPE。這是因爲上面的代碼實際上涉及3個主題:
- 主要 - 在
main
&init
運行 - EDT - 在吉斯是自舉
MyApp
實例 - 搖擺工人 - 哪裏
SwingWorker
正在運行並試圖預熱高速緩存
所以當我們去執行Swing worker時,Guice還沒有機會引導MyApp
實例(因此它的緩存屬性)。
Ay的想法(w /特定代碼示例)我如何讓Guice能夠與Swing的併發模型正常工作?
你在傳遞給'invokeLater'的Runnable中調用'init'。爲什麼它會在主線程而不是EDT線程上運行? –
我真的很想學習一個不是單線程的GUI庫。 – trashgod
謝謝@JeffBowman(+1) - 因爲'SwingWorker'有一些神奇的功能 - 你自己運行這個代碼,你會看到工作代碼在自己的線程中執行,與主和EDT分開。 – smeeb