[英]How do I destroy an adapter before a view when the view is non modal?
我為我的所有應用程序模塊都使用了某種(類似於MVA的)模式。
視圖是TForm
后代:
TSomeView = class(TForm)
...
end;
數據在模型中管理:
TSomeModel = class
public
property DataSet: TDataSet read ...;
end;
視圖和模型通過適配器粘合在一起。
uses
Some.Model, Some.View;
type
TSomeAdapter = class
private
FView : TSomeView;
FModel : TSomeModel;
procedure ClickHandler(Sender: TObject);
public
constructor Create(AOwner: TComponent);
destructor Destroy; override;
procedure Run;
end;
盡管這似乎有些乏味,但將各個部分分開工作非常有效。
到目前為止,我一直使用模態形式,因此適配器實現如下所示:
constructor TSomeAdapter.Create(AOwner: TComponent);
begin
inherited Create;
FModel := TSomeModel.Create,
FView := TSomeView.Create(AOwner);
FView.DataSource.DataSet := FModel.DataSet;
FView.SomeButton.OnClick := ClickHandler;
end;
procedure TSomeAdapter.Run;
begin
FView.ShowModal;
end;
destructor TSomeAdapter.Destroy;
begin
FView.Free;
FModel.Free;
inherited;
end;
這里重要的是,我不斷開析構函數中的事件處理程序和數據集,因為視圖始終首先被銷毀。
調用者使用以下模式創建應用程序模塊:
procedure CallSome;
var
Adapter: TSomeAdapter;
begin
Adapter := TSomeAdapter.Create(...);
try
Adapter.Run;
finally
Adapter.Free;
end;
end;
我正在嘗試使它適應非模式形式。
調用者無法釋放適配器,因為它不知道何時。 因此,調用者代碼現在如下所示:
procedure CallSome;
var
Adapter: TSomeAdapter;
begin
Adapter := TSomeAdapter.Create(...);
Adapter.Run;
// Adapter is now a memory leak
end;
我不想更改銷毀順序,因為我依靠這樣的事實,即我不需要斷開處理程序和數據集的連接。
使用非模式形式時,如何保持銷毀順序(視圖<模型<適配器)?
您必須更改適配器,以便適配器是視圖的所有者,並在關閉時使視圖自毀。 當視圖將被銷毀時,適配器將收到通知。
type
TSomeAdapter = class( TComponent )
private
FView : TSomeView;
FModel : TSomeModel;
FOnEndsRunning : TNotifyEvent;
function GetModel : TSomeModel;
function GetView : TSomeView;
function GetIsRunning : Boolean;
protected
procedure Notification( AComponent : TComponent; Operation : TOperation ); override;
property View : TSomeView read GetView;
property Model : TSomeModel read GetModel;
procedure ClickHandler( Sender : TObject );
public
destructor Destroy; override;
procedure Run;
property IsRunning : Boolean read GetIsRunning;
property OnEndsRunning : TNotifyEvent read FOnEndsRunning write FOnEndsRunning;
end;
{ TSomeAdapter }
destructor TSomeAdapter.Destroy;
begin
FModel.Free;
inherited;
end;
procedure TSomeAdapter.ClickHandler( Sender : TObject );
begin
// DoSomething
end;
function TSomeAdapter.GetIsRunning : Boolean;
begin
Result := Assigned( FView );
end;
function TSomeAdapter.GetModel : TSomeModel;
begin
// lazy initialization of model
if not Assigned( FModel ) then
FModel := TSomeModel.Create;
Result := FModel;
end;
function TSomeAdapter.GetView : TSomeView;
begin
// lazy initialization of view
if not Assigned( FView ) then
begin
FView := TSomeView.Create( Self ); // Owner is this Adapter
FView.DataSource.DataSet := Model.DataSet;
FView.SomeButton.OnClick := ClickHandler;
end;
Result := FView;
end;
procedure TSomeAdapter.Notification( AComponent : TComponent; Operation : TOperation );
begin
inherited;
case Operation of
opInsert :
;
opRemove :
if AComponent = FView then
begin
// forget the view reference
FView := nil;
// destroy the model (optional)
FreeAndNil( FModel );
// notify
if Assigned( OnEndsRunning ) then
OnEndsRunning( Self );
end;
end;
end;
procedure TSomeAdapter.Run;
begin
View.Show;
end;
視圖應該在關閉時釋放自己
TSomeView = class( TForm )
procedure FormClose(Sender: TObject; var Action: TCloseAction);
end;
procedure TSomeView.FormClose(Sender: TObject; var Action: TCloseAction);
begin
Action := caFree;
end;
現在,將通知您適配器是否結束運行
將主窗口句柄傳遞給所有適配器:
procedure CallSome;
var
Adapter: TSomeAdapter;
begin
Adapter := TSomeAdapter.Create(..., FMainView.Handle);
FMainAdapter.Add(Adapter);
Adapter.Run;
end;
附加OnClose
並設置CloseAction
到caNone
:
procedure TSomeAdapter.ViewClose(Sender: TObject; var CloseAction: TCloseAction);
begin
CloseAction := TCloseAction.caNone;
PostMessage(FMainViewHandle, WM_FREE_ADATER, NativeUInt(@Self), 0);
end;
在主適配器中使用TObjectList
並處理WM_FREE_ADAPTER:
constructor TMainAdapter.Create(...);
begin
inherited;
FAdapters := TObjectList.Create;
end;
procedure TMainAdapter.WMFreeAdapter(var Msg: TMessage);
begin
FAdapters.Remove(PAdapter(Msg.WParam)^);
end;
destructor TMainAdapter.Destroy;
begin
FAdapters.Free;
inherited;
end;
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.