網頁

2010年2月24日 星期三

[Java] Concurrency in Swing

參考 Java TutorialsConcurrency in Swing 章節所寫的筆記。

一個好的 Swing 程式會利用 concurrency 去建立不會 "凍結" 的 UI — 無論程式正在做什麼,都會回應使用者的操作。

一個 Swing programmer 將需要處理以下三種類型的 thread:
  1. Initial thread:
    啟動應用程式的 thread
  2. Event dispatch thread:
    所有的 Event-handling 程式都位於此 thread,大部分與 Swing 互動的程式也在此 thread 上執行。
  3. Worker thread:
    也稱做 background thread,需要消耗較長時間的 task 位於此 thread。

一個 Swing 程式應該這樣寫:
  1. Initial thread 沒有太多事要做,它最主要的工作就是建立一個 Runnable 物件負責建立 GUI,並且將這個物件交由 event dispatch thread 負責執行。 
     
  2. 將建立 GUI 交由 event dispatch thread 負責的方法為 javax.swing.SwingUtilities.invokeLater 或著 javax.swing.SwingUtilities.invokeAndWait,這兩個 method 都傳入一個 Runnable 物件。它們的差別在於 invokeLater 只會將工作加入排程後便返回,而 invokeAndWait 將會等待工作執行結束後才返回。
         
  3. 在 Applet 中,應該在 init 方法中呼叫 invokeAndWait,否則 init 可能會在 GUI 建立完成前就返回,這將可能造成瀏覽器啟動 applet 時的問題。
         
  4. 在其他類型的程式中,建立 GUI 通常都是 initial thread 中的最後一項工作,因此無論呼叫 invokeLater 或 invokeAndWait 皆可。
  5. 一旦 GUI 建立完成,程式的主要運作就變成 event-driven。其中較短的 task 將交由 event dispath thread,較長的 task 則交給 worker thread。

2010年2月14日 星期日

[GWT] 使用外部 resource

使用外部 resourceDeclarative Layout with UensureInjected()iBinder 其中的一個章節,並且已經由 PsMonkey 完成此文的翻譯

我在實作這個章節所提及的方法時,遭遇了一點問題,因此提出來與大家分享。

在此說明一下我所遭遇的問題:

  1. 我寫了一個名為 Resources 的 interface,打算在其他的 template file 中使用,內容如下。


    public interface Resources extends ClientBundle {
        @Source("Style.css")
        MyStyle style();
    
        @Source("Logo.jpg")
        ImageResource logo();
    
        public interface MyStyle extends CssResource {
            String red();
        }
    } 
  2. 當然 Style.css 與 Logo.jpg 都是存在的,並且 Sytle.css 中也定義了 .red
  3. 然而當我使用如下的 template file 去使用 Resources 時,雖然 Image 能夠正常顯示,但是所有與 CssResource 相關的設定都沒有作用。


    <ui:UiBinder xmlns:ui='urn:ui:com.google.gwt.uibinder'
        xmlns:g='urn:import:com.google.gwt.user.client.ui'>
    
      <ui:with field='res' type='com.my.app.widgets.logoname.Resources'/>
    
      <g:HTMLPanel>
    
        <g:Image resource='{res.logo}'/>
    
        <div class='{res.style.red}'>
          this text should be red
        </div>
    
      </g:HTMLPanel>
    </ui:UiBinder> 
  4. 如果使用 Firebugs 等工具觀察, 會看到對應的 HTML 元素確實被指定了 CSS class,然而在 CSS file 內卻沒有對應的設定存在。

解決的方法為,建立一個 Resources 實體並呼叫 CssResource 的 ensureInjected() 方法,以確保 CssResource 有被加入 DOM 中。
Resources resources = GWT.create(Resources.class);
resources.style().ensureInjected(); 

值得注意的是,無論創造了幾個 MyStyle 實體(包含在 Resources 內),也只需要執行一次 ensureInjected() 。所以合理的作法應該是在 EntryPoint 內呼叫 ensureInjected(),如果希望所有的頁面都能使用同一個 Resources 實體,可以將此處建立的物件傳給其他頁面,詳細作法參考同一篇文章中的 Share resource instances 章節(中譯: 共用 resource 的 instances)。