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

來源:互聯網
上載者:User
筆記|圖形
本文部分內容和靈感來自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);}
這樣的檢查保證了任何控制項在建立時都有父控制項。當我們調用某個Composite的dispose()方法時,它會調用:


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繼承自Canvas,Canvas繼承自Composite,最終這條繼承鏈一直連到Widget類。我們在建立Shell樣本的時候,需要告訴構造方法它的父控制項是什麼,在這裡就是display。於是當我們最後調用display.dispose()時,雖然我們沒有明確寫shell.dispose(),我們的Shell執行個體也隨之銷毀了。

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

 


相關文章

Cloud Intelligence Leading the Digital Future

Alibaba Cloud ACtivate Online Conference, Nov. 20th & 21st, 2019 (UTC+08)

Register Now >

11.11 Big Sale for Cloud

Get Unbeatable Offers with up to 90% Off,Oct.24-Nov.13 (UTC+8)

Get It Now >

Alibaba Cloud Free Trial

Learn and experience the power of Alibaba Cloud with a free trial worth $300-1200 USD

Learn more >

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。