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



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

fTimer := TTimer.Create(nil);
fTimer.Interval := 1;
fTimer.OnTimer := OnTimer;
fTimer.Enabled := True;

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;

当我启动应用程序时,OnTimer事件每10毫秒就会发射一次,而不是每1毫秒。但是,如果我触摸屏幕并将手指移动,则每1.3-1.5 ms射击事件。

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

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

关于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;

那么工作还可以,事件每2毫秒发射一次(无tthread.shnenchronize每1ms),而这手指或不在屏幕上。

与VCL的TTimer不同,Android上的FMX TTimer效率很低。

当计时器间隔通过时,Android使用回调函数(在Androidapi.Timer单元中)通知FMX。该回调是由工作线程调用的,它将计时器推入线程安全队列(在FMX.Platform.Android单元中)。

当主UI线程定期检查已待定的UI消息时,它也会检查计时器队列,如果有任何计时器排队,则调用其OnTimer事件处理程序(按已排队的顺序)。

)。

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

因此,无法保证1 ms的计时器会在1 ms间隔附近发射其OnTimer事件处理程序。这也可能解释了为什么UI活动增加可以使OnTimer事件更频繁地触发,因为UI消息经常处理。

这与基于WM_TIMER UI消息的VCL的TTimer不同,这是一个低优先级消息,仅在没有其他UI消息待处理的情况下才会生成。当它生成时,它会直接派遣到TTimer的内部窗口,没有其他排队来添加额外的开销层。但是,UI活动的增加将减慢TTImer.OnTimer事件的速度,而不是加快速度。


TThread.Synchronize()的情况下,每当需要处理待处理同步请求时,它会积极地通知主UI线程,从而允许主UI线程检查并执行Sync'Ed过程,而不是较晚。

最新更新