当手指触摸屏幕时,为什么Android上的Timer会更准确?

and*_*rey 3 delphi performance android firemonkey android-timer

在Delphi 10.1柏林,我正在制作一个Android应用程序.我创建了一个这样的计时器:

fTimer := TTimer.Create(nil);
fTimer.Interval := 1;
fTimer.OnTimer := OnTimer;
fTimer.Enabled := True;
Run Code Online (Sandbox Code Playgroud)

在这种情况OnTimer下,我只是这样做:

procedure TMyForm.OnTimer(Sender: TObject);
begin
  MyStopWatch.Stop;
  Inc(acounter);
  if acounter mod 1000 = 0 then 
    allog('delay', FloatToStr(xStopWatch.Elapsed.TotalMilliseconds));
  MyStopWatch := TStopWatch.StartNew;
end;
Run Code Online (Sandbox Code Playgroud)

当我启动应用程序时,OnTimer事件每10毫秒而不是每1毫秒触发一次.但是,如果我触摸屏幕并用手指移动它,则事件每隔1.3-1.5毫秒触发一次.

有人可以向我解释这种奇怪的行为吗?

当我的手指触摸屏幕时,为什么应用程序(或至少是计时器)更具反应性?如何使应用程序始终被反应?

关于J的评论..

我认为这不是小生命(但我不确定),因为如果我使用线程而不是像这样的计时器:

TThread.createAnonymousThread(
  procedure
  var MyStopWatch: TstopWatch;
      acounter: integer;
  begin

    acounter := 0;
    MyStopWatch :=  TStopWatch.StartNew;

    while True do begin
      TThread.synchronize(nil,
        procedure
        begin
          MyStopWatch.Stop;
          Inc(acounter);
          if acounter mod 1000 = 0 then
            allog('delay', FloatToStr(MyStopWatch.Elapsed.TotalMilliseconds));
          MyStopWatch := TStopWatch.StartNew;
        end);
      sleep(1);
    END;

  end).start;
Run Code Online (Sandbox Code Playgroud)

然后它工作正常,事件每2毫秒触发一次(每1毫秒没有TThread.synchronize),这个手指或不在屏幕上.

Rem*_*eau 11

与VCL不同TTimer,TTimerAndroid上的FMX 非常低效.

当计时器间隔过去时,Android会使用回调函数(在Androidapi.Timer单元中)通知FMX .该回调由工作线程调用,并将定时器推送到线程安全队列(在FMX.Platform.Android单元中).

当主UI线程定期检查挂起的UI消息时,它还会检查计时器队列,如果任何计时器排队,则OnTimer调用它们的事件处理程序(按它们排队的顺序).

但是,如果没有待处理的UI消息,FMX可能会延迟检查计时器队列!然后,一旦处理完所有UI消息,在再次处理事件之前可能会有延迟.这一切都取决于FMX应用程序的内部状态.

因此,无法保证1 ms定时器将以OnTimer1 ms的间隔触发其事件处理程序.它还可以解释为什么UI活动的增加可以允许OnTimer事件更频繁地触发,因为UI消息正在被更频繁地处理.

这与VCL不同TTimer,后者基于WM_TIMERUI消息,这是一种低优先级消息,仅在没有其他UI消息未决时生成.在生成它时,它会直接发送到TTimer内部窗口,不需要额外的排队来添加额外的开销层.但是,UI活动的增加将减缓TTImer.OnTimer事件的发放速度,而不是加快速度.


在这种情况下TThread.Synchronize(),它会在需要处理挂起的同步请求时主动通知主UI线程,从而允许主UI线程更快地检查并执行同步过程.