Android原生消息处理与FMX平台服务消息处理的区别与消息机制
一、通过TApplicationEventMessage获取消息
{ // 原理: Application events }
TApplicationEvent = (FinishedLaunching, BecameActive, WillBecomeInactive, EnteredBackground, WillBecomeForeground, WillTerminate, LowMemory, TimeChange, OpenURL);
TApplicationEventHelper = record helper for TApplicationEvent
const
aeFinishedLaunching = TApplicationEvent.FinishedLaunching deprecated 'Use TApplicationEvent.FinishedLaunching';
aeBecameActive = TApplicationEvent.BecameActive deprecated 'Use TApplicationEvent.BecameActive';
aeWillBecomeInactive = TApplicationEvent.WillBecomeInactive deprecated 'Use TApplicationEvent.WillBecomeInactive';
aeEnteredBackground = TApplicationEvent.EnteredBackground deprecated 'Use TApplicationEvent.EnteredBackground';
aeWillBecomeForeground = TApplicationEvent.WillBecomeForeground deprecated 'Use TApplicationEvent.WillBecomeForeground';
aeWillTerminate = TApplicationEvent.WillTerminate deprecated 'Use TApplicationEvent.WillTerminate';
aeLowMemory = TApplicationEvent.LowMemory deprecated 'Use TApplicationEvent.LowMemory';
aeTimeChange = TApplicationEvent.TimeChange deprecated 'Use TApplicationEvent.TimeChange';
aeOpenURL = TApplicationEvent.OpenURL deprecated 'Use TApplicationEvent.OpenURL';
end;
TApplicationEventData = record
Event: TApplicationEvent;
Context: TObject; //:适用于任何对象的订阅后的消息处理
constructor Create(const AEvent: TApplicationEvent; AContext: TObject);
end;
TApplicationEventMessage = class (System.Messaging.TMessage<TApplicationEventData>) //:delphi原生调用
public //:具有独立于FMX的通用的消息机制,即VCL也适用
constructor Create(const AData: TApplicationEventData);
end;
TApplicationEventHandler = function (AAppEvent: TApplicationEvent; AContext: TObject): Boolean of object;
//用下面的方式订阅消息,你可以处理和发布任意对象的任何消息:
//FEventManagerID:=
TMessageManager.DefaultManager.SubscribeToMessage(
const AMessageClass: TClass; const AListener: TMessageListener
): Integer;
//FEventManagerID:=
TMessageManager.DefaultManager.SubscribeToMessage(
const AMessageClass: TClass; const AListenerMethod: TMessageListenerMethod
): Integer;
TMessageListener = reference to procedure(const Sender: TObject; const M: TMessage);
TMessageListenerMethod = procedure (const Sender: TObject; const M: TMessage) of object;
/// <summary>Base class for all messages</summary>
TMessageBase = class abstract;
TMessage = TMessageBase;
{$NODEFINE TMessage} // Avoid ambiguity with 'Winapi.Messages.TMessage'
TMessage<T> = class (TMessage)
protected
FValue: T;
public
constructor Create(const AValue: T);
destructor Destroy; override;
property Value: T read FValue;
end;
比如:订阅一个TEdit的字体属性对象的消息:
MsgSubscriptionId2 := //System.Messaging.TMessageListener:
MessageManager.SubscribeToMessage(
TMessage<TEdit>,
procedure(
const Sender: TObject;
const M: TMessage )
begin
(M as TMessage<TEdit>).Value.StyledSettings
:=[TStyledSetting.Style];
(M as TMessage<TEdit>).Value.TextSettings.Font.Family:='微软雅黑';
(M as TMessage<TEdit>).Value.TextSettings.Font.Size:=20;
(M as TMessage<TEdit>).Value.TextSettings.FontColor:=TAlphaColorRec.Red;
end);
//返回用消息管理器订阅的监听方法或监听事件来发消息:
//:MessageManager.SendMessage:
//:OnCreate等地方:写了订阅代码:
var
MessageManager: TMessageManager;
AMessage: TMessage;
begin
MessageManager := TMessageManager.DefaultManager;
AMessage := TMessage<TEdit>.Create(Edit2);
MessageManager.SendMessage(Sender, AMessage, true);
//MessageManager.SendMessage(Sender, AMessage, false);
//:true:相当于false后立即:AMessage.DisposeOf;
//:每个TMessage<T>在订阅时SubscribeToMessage产生唯一识别1个id
//:最后TMessage<T>在Create并SendMessage用完之后必须释放DisposeOf,否则内存泄漏
结果:
二、IFMXApplicationEventService通过FMX平台服务获取消息
在学习《delphi调用及封装Android原生控件》的直播课程过程中,有朋友粘了这段代码通过平台服务TPlatformServices,我们也经常用到类似接口调用的方式,但其实还是与1、TApplicationEventMessage的实现是有区别的。
var SvcEvents:IFMXApplicationEventService;
// 后台事件
if TPlatformServices.Current.SupportsPlatformService(IFMXApplicationEventService, IInterface(SvcEvents)) then
SvcEvents.SetApplicationEventHandler(HandleAppEvent);
//HandleAppEvent
function TFormMain.HandleAppEvent(AAppEvent: TApplicationEvent; AContext: TObject): Boolean;
begin
// APP进入到后台,10秒之内切回到前台,不做二次验证。
// APP进入到后台,超过10秒切回到前台,再次进行指纹验证。
// 记录进入后台的时间data 时入后台时检查时间差 10以内不需要验证
//
case AAppEvent of
TApplicationEvent.FinishedLaunching:
; // ShowMessage('FinishedLaunching');
TApplicationEvent.BecameActive: // 主窗体重新激活也会触发 很频繁一般建议少用
// begin
// ShowMessage('BecameActive'); // 第一次运行app触发,从后台切换过来也触发
;
TApplicationEvent.WillBecomeInactive: // ShowMessage('WillBecomeInactive')
;
TApplicationEvent.EnteredBackground:
begin
end;
// ShowMessage('EnteredBackground'); //切换到后台
TApplicationEvent.WillBecomeForeground: // ShowMessage('WillBecomeForeground'); // 从后台切换到前台
if Gsettingjson.TimeLimit <> tlNone then
begin
end;
TApplicationEvent.WillTerminate:
; // ShowMessage('WillTerminate');
TApplicationEvent.LowMemory:
;
TApplicationEvent.TimeChange:
;
TApplicationEvent.OpenURL:
;
end;
Result := True;
end;
// 原理:
IFMXApplicationEventService = interface(IInterface)
['{F3AAF11A-1678-4CC6-A5BF-721A24A676FD}']
procedure SetApplicationEventHandler(AEventHandler: TApplicationEventHandler);
end; //:1、FMX接口调用,而且只能处理应用程序级别的事件消息TApplicationEventHandler,2、而非任意对象TObject级别的事件消息,比如一个TEdit的任意属性对象的消息
//:3、FMX所特有的,VCL不适用,4、是用接口去写实现,来达到目的的,5、另VCL下调用FMX控件等代码时,也不适用的
三、参见: