You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在跨平台FMX应用的多动态帧中触发DoAfterPermissions过程?

解决方案:FMX动态Frame权限刷新触发方案

以下三种方案均支持Windows、Android、iOS平台,无平台依赖代码,可根据项目现状选择:


方案1:接口规范+接口列表管理

类型安全、可维护性最高的方案,适合长期迭代的项目。

实现步骤:

  1. 定义统一接口,所有Frame实现该接口:
type
  IPermissionRefreshable = interface
    ['{E7D5F9C1-3B7A-4F3C-8C5D-1234567890AB}'] // 替换为自行生成的GUID
    procedure DoAfterPermissions;
  end;

// 示例Frame实现
type
  TMyDynamicFrame = class(TFrame, IPermissionRefreshable)
  public
    procedure DoAfterPermissions;
  end;

procedure TMyDynamicFrame.DoAfterPermissions;
begin
  // 权限刷新后的业务逻辑
end;
  1. 主窗体维护接口列表,创建Frame时加入列表:
type
  TMainForm = class(TForm)
  private
    FRefreshableFrames: TInterfaceList;
  public
    constructor Create(AOwner: TComponent); override;
    destructor Destroy; override;
    procedure RefreshPermissions; // 权限刷新入口方法
  end;

constructor TMainForm.Create(AOwner: TComponent);
begin
  inherited;
  FRefreshableFrames := TInterfaceList.Create;
end;

destructor TMainForm.Destroy;
begin
  FRefreshableFrames.Free;
  inherited;
end;

// 创建动态Frame的代码
procedure TMainForm.CreateDynamicFrame;
var
  LFrame: TMyDynamicFrame;
  LRefreshable: IPermissionRefreshable;
begin
  LFrame := TMyDynamicFrame.Create(Self);
  LFrame.Parent := pnlContainer; // 挂载到界面容器
  // 将接口加入列表,自动维护生命周期
  if Supports(LFrame, IPermissionRefreshable, LRefreshable) then
    FRefreshableFrames.Add(LRefreshable);
end;
  1. 权限刷新完成后遍历调用:
procedure TMainForm.RefreshPermissions;
var
  I: Integer;
  LRefreshable: IPermissionRefreshable;
begin
  // 执行权限刷新逻辑...
  
  // 触发所有Frame的DoAfterPermissions
  for I := 0 to FRefreshableFrames.Count - 1 do
  begin
    LRefreshable := IPermissionRefreshable(FRefreshableFrames[I]);
    if Assigned(LRefreshable) then
      LRefreshable.DoAfterPermissions;
  end;
end;

优点:类型安全,无RTTI依赖,接口自动管理生命周期;缺点:需所有Frame实现接口,对已有项目有改造量。


方案2:组件列表+FreeNotification(兼容已有Frame)

适合已有大量未统一基类/接口的Frame,通过组件生命周期通知自动维护活跃列表。

实现步骤:

  1. 主窗体维护Frame列表,创建时注册销毁通知:
type
  TMainForm = class(TForm)
  private
    FActiveFrames: TList<TFrame>;
    procedure Notification(AComponent: TComponent; Operation: TOperation); override;
  public
    constructor Create(AOwner: TComponent); override;
    destructor Destroy; override;
    procedure RefreshPermissions;
  end;

constructor TMainForm.Create(AOwner: TComponent);
begin
  inherited;
  FActiveFrames := TList<TFrame>.Create;
end;

destructor TMainForm.Destroy;
begin
  FActiveFrames.Free;
  inherited;
end;

// 创建动态Frame的代码
procedure TMainForm.CreateDynamicFrame;
var
  LFrame: TMyDynamicFrame;
begin
  LFrame := TMyDynamicFrame.Create(Self);
  LFrame.Parent := pnlContainer;
  FActiveFrames.Add(LFrame);
  // 注册销毁通知,Frame释放时自动从列表移除
  LFrame.FreeNotification(Self);
end;

// 处理Frame销毁通知
procedure TMainForm.Notification(AComponent: TComponent; Operation: TOperation);
var
  LIndex: Integer;
begin
  inherited;
  if (Operation = opRemove) and (AComponent is TFrame) then
  begin
    LIndex := FActiveFrames.IndexOf(TFrame(AComponent));
    if LIndex <> -1 then
      FActiveFrames.Delete(LIndex);
  end;
end;
  1. 权限刷新后通过RTTI调用目标方法:
uses
  System.Rtti;

procedure TMainForm.RefreshPermissions;
var
  LFrame: TFrame;
  LContext: TRttiContext;
  LMethod: TRttiMethod;
begin
  // 执行权限刷新逻辑...
  
  // 遍历活跃Frame调用DoAfterPermissions
  for LFrame in FActiveFrames do
  begin
    LContext := TRttiContext.Create;
    try
      LMethod := LContext.GetType(LFrame.ClassType).GetMethod('DoAfterPermissions');
      if Assigned(LMethod) then
        LMethod.Invoke(LFrame, []);
    finally
      LContext.Free;
    end;
  end;
end;

优点:无需修改已有Frame,兼容现有代码;缺点:依赖RTTI,有轻微性能开销(可忽略),类型检查较弱。


方案3:观察者模式(事件订阅)

通过主窗体发布事件,Frame自动订阅/取消订阅,无需维护列表。

实现步骤:

  1. 主窗体定义权限刷新事件:
type
  TPermissionsRefreshedEvent = procedure of object;

type
  TMainForm = class(TForm)
  private
    FOnPermissionsRefreshed: TPermissionsRefreshedEvent;
  public
    property OnPermissionsRefreshed: TPermissionsRefreshedEvent read FOnPermissionsRefreshed write FOnPermissionsRefreshed;
    procedure RefreshPermissions;
  end;

procedure TMainForm.RefreshPermissions;
begin
  // 执行权限刷新逻辑...
  
  // 触发事件
  if Assigned(FOnPermissionsRefreshed) then
    FOnPermissionsRefreshed;
end;
  1. Frame在创建/销毁时订阅/取消订阅:
type
  TMyDynamicFrame = class(TFrame)
  protected
    procedure DoAfterPermissions;
  public
    constructor Create(AOwner: TComponent); override;
    destructor Destroy; override;
  end;

constructor TMyDynamicFrame.Create(AOwner: TComponent);
begin
  inherited;
  // 订阅主窗体事件(兼容Owner非主窗体的情况)
  if Screen.MainForm is TMainForm then
    TMainForm(Screen.MainForm).OnPermissionsRefreshed := TMainForm(Screen.MainForm).OnPermissionsRefreshed + DoAfterPermissions;
end;

destructor TMyDynamicFrame.Destroy;
begin
  // 取消订阅,避免访问违规
  if Screen.MainForm is TMainForm then
    TMainForm(Screen.MainForm).OnPermissionsRefreshed := TMainForm(Screen.MainForm).OnPermissionsRefreshed - DoAfterPermissions;
  inherited;
end;

procedure TMyDynamicFrame.DoAfterPermissions;
begin
  // 权限刷新后的业务逻辑
end;

优点:代码简洁,无需维护列表;缺点:需确保Frame销毁时取消订阅,否则会导致访问违规或内存泄漏。


内容的提问来源于stack exchange,提问作者JakesF

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.21 08:18:13