如何在跨平台FMX应用的多动态帧中触发DoAfterPermissions过程?
解决方案:FMX动态Frame权限刷新触发方案
以下三种方案均支持Windows、Android、iOS平台,无平台依赖代码,可根据项目现状选择:
方案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;
- 主窗体维护接口列表,创建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;
- 权限刷新完成后遍历调用:
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,通过组件生命周期通知自动维护活跃列表。
实现步骤:
- 主窗体维护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;
- 权限刷新后通过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自动订阅/取消订阅,无需维护列表。
实现步骤:
- 主窗体定义权限刷新事件:
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;
- 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
相关产品推荐
相关产品推荐

