Read Sean

          Read me, read Sean.
          posts - 508, comments - 655, trackbacks - 9, articles - 4

          [Eclipse筆記]在SWT中有效的管理圖形系統資源

          Posted on 2005-03-20 17:11 laogao 閱讀(770) 評論(0)  編輯  收藏 所屬分類: On JavaOn Eclipse

          本文部分內容和靈感來自eclipse.org網站,特此聲明。更多內容,請參考:

          http://eclipse.org/articles/Article-SWT-Design-2/SWT-Design-2.html

           

          由于SWT直接跟操作系統打交道,所以我們需要在處理系統的圖形資源時格外小心,以免不必要的資源泄漏。所幸SWT提供了很好的資源管理機制,我們絕大多數情況下需要做的只是確保兩條原則:

          第一條原則 誰分配誰銷毀

          第二條原則 父控件銷毀的同時銷毀子控件

           

          下面我們分別來看一看這兩條在實際中是如何體現的。

          先看第一條原則。乍一看這似乎是廢話,但是在實際中往往并非那么簡單。首先,構造方法不等于分配資源,實際上分配資源可以發生在一個類中的任何地方以及一個對象生命周期的任何時候,只要你的代碼告訴操作系統這樣做。你必須保證所有由你分配的資源當你不再使用時調用其dispose()方法;同時你也必須保證所有不是由你分配的資源不要隨便調用其dispose()方法,否則很可能會影響到實際分配的那段相關代碼的正常工作。好消息是,為了明確和簡化這第一條原則所規定的分工,SWT在設計之初就確定下來,所有基于系統資源的SWT類都在其構造方法中完成所有所需的資源分配,在其他方法中則沒有任何分配系統資源的動作,所以我們可以幸運的這樣看待SWT的資源管理:如果你調用了某個SWT類的構造方法,那么就由你來調用其dispose()方法釋放資源;如果你沒有調用某個SWT類的構造方法,即便你使用了這個類的實例,也不應該由你來調用其dispose()方法。就是這么明確。

          比方講,你new了一個Font對象,那么當你不再需要它時,就應該調用dispose();如果你通過某個控件的getFont()方法取得一個Font對象并使用后,你不應該去銷毀它,而應該交給那個具體的控件去處理。

          對于第二條原則,SWT有一個很好的機制去支持它,那就是,所有的SWT控件,具體講,Composite類及其子類的實例,都必須有一個父控件,這個父控件的引用在子控件的構造方法中被傳入。需要注意的是,所有這些控件的不帶參數的構造方法都只有默認訪問級別,于是我們不能在自己的SWT程序中直接調用這樣的默認構造方法而只能提供一個父控件的引用,而在Widget類(Composit的父類)的帶參數構造方法中,它會調用如下方法:

          void checkParent (Widget parent) {
                 
          if (parent == null) error (SWT.ERROR_NULL_ARGUMENT);
                 parent.checkWidget ();
          }

          進而:

          protected void checkWidget () {
                 Display display 
          = this.display;
                 
          if (display == null) error (SWT.ERROR_WIDGET_DISPOSED);
                 
          if (display.thread != Thread.currentThread ()) error (SWT.ERROR_THREAD_INVALID_ACCESS);
                 
          if ((state & DISPOSED) != 0) error (SWT.ERROR_WIDGET_DISPOSED);
          }

          這樣的檢查保證了任何控件在創建時都有父控件。當我們調用某個Compositedispose()方法時,它會調用:

          void releaseChildren () {
                 Control [] children 
          = _getChildren ();
                 
          for (int i=0; i<children.length; i++{
                        Control child 
          = children [i];
                        
          if (!child.isDisposed ()) child.releaseResources ();
                 }

          }

          其中的_getChildren()方法通過OS對象的方法遍歷控件的子控件,然后匯總到一起分別調用releaseResources()方法釋放控件和句柄。

          回到上次的SimplestSWT的例子:


          package sean.test.swt;

          import org.eclipse.swt.widgets.Display;
          import org.eclipse.swt.widgets.Shell;

          public class SimplestSWT {

              
          public static void main(String[] args) {
                  Display display 
          = new Display();
                  Shell shell 
          = new Shell(display);
                  shell.pack();
                  shell.open();
                  
          while (!shell.isDisposed()) {
                      
          if (!display.readAndDispatch()) {
                          display.sleep();
                      }

                  }

                  display.dispose();
              }


          }

           

          這當中,Display是一個頂層的設備,它繼承自Device類,而Device類實現了Drawable接口。Shell的父類是Decoration,而Decoration繼承自CanvasCanvas繼承自Composite,最終這條繼承鏈一直連到Widget類。我們在創建Shell示例的時候,需要告訴構造方法它的父控件是什么,在這里就是display。于是當我們最后調用display.dispose()時,雖然我們沒有明確寫shell.dispose(),我們的Shell實例也隨之銷毀了。

          這就是SWT的資源管理機制,稍有例外的是MenuItemsetMenu()方法和ControlsetMenu()方法,它們通過顯式調用setMenu的方式注冊自己的父控件。

           

          主站蜘蛛池模板: 三亚市| 靖安县| 延庆县| 洱源县| 盘锦市| 寿阳县| 遂宁市| 荥阳市| 浦北县| 伊金霍洛旗| 泸水县| 和平区| 香河县| 洪泽县| 石楼县| 伊春市| 镇赉县| 米泉市| 乃东县| 天峨县| 姜堰市| 健康| 洛川县| 大英县| 鸡东县| 广宗县| 石门县| 静安区| 海口市| 绥宁县| 唐山市| 石棉县| 图木舒克市| 绿春县| 伊金霍洛旗| 凤城市| 云和县| 永兴县| 宜君县| 龙胜| 陇南市|