使用多窗体时, 关于节约内存和加快启动速度的思考与尝试
使用多窗體時(shí), 關(guān)于節(jié)約內(nèi)存和加快啟動(dòng)速度的思考與嘗試
剛接觸 Delphi 時(shí), 曾以為 Pi 是個(gè)常量; 當(dāng)我知道它是個(gè)函數(shù)時(shí), 曾被觸動(dòng).
但 Pi 返回的不過(guò)是占 10 個(gè)字節(jié)的 Extended 類型, 后來(lái)竟發(fā)現(xiàn)一些對(duì)象也這樣干, 譬如:
function Clipboard: TClipboard; { Clipbrd } function Printer: TPrinter; { Printers } function Languages: TLanguages; { SysUtils } function RootSprigList: TRootSprigList; { TreeIntf } function ComClassManager: TComClassManager; { ComObj } function ThemeServices: TThemeServices; { Themes } function PropertyCategoryList: TPropertyCategoryList; { PropertyCategories }//這或許已是 Delphi 2010 中類似對(duì)象的全部.
特別是其中常用的 Clipboard、Printer、Languages, 無(wú)需建立就可以像對(duì)象一樣使用它們.
這是怎么實(shí)現(xiàn)的呢? 查看源碼, 它們都有類似的結(jié)構(gòu)脈絡(luò)(以 Clipboard 對(duì)象為例):
interface ... function Clipboard: TClipboard; { 這一般在 interface 的尾部 } ... implementation ... varFClipboard: TClipboard; { 句柄變量 } ... function Clipboard: TClipboard; { 函數(shù)實(shí)現(xiàn) } beginif FClipboard = nil thenFClipboard := TClipboard.Create;Result := FClipboard; end; ...
當(dāng)然它們還有個(gè)釋放的問(wèn)題, 但我覺(jué)得這些對(duì)象往往也是它所在的單元也在頻繁地使用, 一般到最后釋放.
它們巧妙的是:
在我們不使用時(shí), 它們并沒(méi)有建立;
有使用時(shí)立即建立;
再使用時(shí)也不會(huì)重復(fù)建立.
真是非常簡(jiǎn)單而巧妙的思路!
不能不提另外兩個(gè)相似的對(duì)象:
Application {Forms.TApplication} Screen {Forms.TScreen}//這個(gè)兩個(gè)更常用, 但它們不是函數(shù), 的確是對(duì)象變量; 它們是在程序生存期一直存在的.
當(dāng)一個(gè)工程有多個(gè)窗體時(shí)(恐怕單窗體的程序很少), 那些副窗體能否動(dòng)態(tài)建立呢? 這樣做肯定會(huì)節(jié)約資源、加快啟動(dòng)速度, 我想這無(wú)須測(cè)試.
上面的做法給了我們很好的借鑒, 不過(guò)我想到了兩種方法: 1、動(dòng)態(tài)建立; 2、像上面一樣通過(guò)函數(shù)建立.
不管用哪種方法, 都先要禁止程序默認(rèn)的對(duì)窗體的自動(dòng)建立, 修改如圖:
當(dāng)然也可以直接從工程文件中刪除相關(guān)的建立代碼.
?
//此時(shí), 我們已經(jīng)不能使用如下代碼打開(kāi)窗體了: procedure TForm1.Button1Click(Sender: TObject); beginForm2.Show; { 這會(huì)出錯(cuò), 因?yàn)榇藭r(shí) Form2 還沒(méi)有建立 } end;//可以這樣: procedure TForm1.Button1Click(Sender: TObject); beginForm2 := TForm2.Create(Application);Form2.Show; end;//但如果想上面這樣, Form2 之后又駐留內(nèi)存了, 怎么釋放它呢? 難道要和 Application 一起釋放嗎? //我們的目的是節(jié)約內(nèi)存, 能不能這樣?: procedure TForm1.Button1Click(Sender: TObject); beginForm2 := TForm2.Create(Application);Form2.Show; { 但 Form2.ShowModal; 可以 }Form2.Free; end;//嘗試上面的代碼, 窗體剛剛顯示就被釋放了, 此路不通! //還是有解決方案的, 在 Form2 的 OnClose 事件中寫(xiě)點(diǎn)代碼: procedure TForm2.FormClose(Sender: TObject; var Action: TCloseAction); beginAction := caFree;{ caNone, caHide, caFree, caMinimize 分別是: 取消、隱藏、釋放、最小化 } end;//這樣 Form1 中的調(diào)用代碼也可以簡(jiǎn)化如下: procedure TForm1.Button1Click(Sender: TObject); beginwith TForm2.Create(nil) do Show; end;
這是第一方案, 第二方案準(zhǔn)備學(xué)習(xí)使用前面提到的 Clipboard 等設(shè)計(jì)手法.
模仿 Clipboard 的實(shí)現(xiàn), 我們可以把 Form2 所在的 Unit2 單元改寫(xiě)為:
unit Unit2;interfaceusesWindows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,Dialogs;typeTForm2 = class(TForm)procedure FormClose(Sender: TObject; var Action: TCloseAction);end;function Form2: TForm2;implementation{$R *.dfm}varFForm: TForm2;function Form2: TForm2; beginif FForm = nil thenFForm := TForm2.Create(Application);Result := FForm; end;procedure TForm2.FormClose(Sender: TObject; var Action: TCloseAction); beginAction := caFree; end;end.
這里的窗體和 Clipboard 還是有區(qū)別, 因?yàn)槲覀冊(cè)谟猛暌院笠R上釋放, 所以代碼可以簡(jiǎn)化為:
unit Unit2;interfaceusesWindows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,Dialogs;typeTForm2 = class(TForm)procedure FormClose(Sender: TObject; var Action: TCloseAction);end;function Form2: TForm2;implementation{$R *.dfm}function Form2: TForm2; beginResult := TForm2.Create(nil); end;procedure TForm2.FormClose(Sender: TObject; var Action: TCloseAction); beginAction := caFree; end;end.
這樣我們?cè)谥鞔绑w又可以這樣調(diào)用了:
procedure TForm1.Button1Click(Sender: TObject); beginForm2.Show; end;{ 這和 Delphi 默認(rèn)的區(qū)別可大了, 這里的 Form2 是個(gè)函數(shù); 動(dòng)態(tài)建立、動(dòng)態(tài)釋放 }
總結(jié)
以上是生活随笔為你收集整理的使用多窗体时, 关于节约内存和加快启动速度的思考与尝试的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: 【线性代数】基础理论归纳
- 下一篇: Delphi 与C系列区别之已见(一)