问题描述
在Delphi 10.1 Berlin中,我正在开发一个Android应用程序.我创建了一个这样的计时器:
In Delphi 10.1 Berlin, I'm making an Android app. I created a timer like this:
fTimer := TTimer.Create(nil);
fTimer.Interval := 1;
fTimer.OnTimer := OnTimer;
fTimer.Enabled := True;
在 OnTimer
事件中,我只是这样做:
In the OnTimer
event, I simply do this:
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;
启动应用程序时,每10毫秒(而不是每1毫秒)触发一次 OnTimer
事件.但是,如果我触摸屏幕并在屏幕上移动手指,则该事件每1.3-1.5毫秒触发一次.
When I launch the app, the OnTimer
event is fired every 10 ms instead of every 1 ms. However, if I touch the screen and move my finger around it, the event is fired every 1.3-1.5 ms instead.
有人可以向我解释这种奇怪的行为吗?
Can someone explain this strange behavior to me?
当我的手指触摸屏幕时,为什么该应用程序(或至少是计时器)反应更快?如何使应用程序始终保持这种反应状态?
Why is the app (or at least the timer) more reactive when my finger is touching the screen? How do I make the app always be this reactive?
关于J ..的评论
我认为这不是巴特里生活(但我不确定),因为如果我使用线程而不是像这样的计时器:
it's not baterry life i think (but i m not sure) because if I use a thread instead of a timer like this :
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.synchronize每1毫秒同步),并且手指是否在屏幕上.
Then it's work ok, the event is fired every 2 ms (without TThread.synchronize every 1ms), and this finger or not on the screen.
推荐答案
与VCL的 TTimer
不同,Android上FMX的 TTimer
效率很低.
Unlike VCL's TTimer
, FMX's TTimer
on Android is quite inefficient.
当计时器间隔过去时,Android使用回调函数(在 Androidapi.Timer
单元中)通知FMX.该回调由工作线程调用,并将计时器推入线程安全队列(在 FMX.Platform.Android
单元中).
When the timer interval elapses, Android notifies FMX using a callback function (in the Androidapi.Timer
unit). That callback is called by a worker thread, and it pushes the timer into a thread-safe queue (in the FMX.Platform.Android
unit).
当主UI线程定期检查未决的UI消息时,它还会检查计时器队列,如果有任何计时器排队,则将调用其 OnTimer
事件处理程序(以它们被处理的顺序)排队).
When the main UI thread checks for pending UI messages periodically, it also checks the timer queue, and if any timers are queued then their OnTimer
event handlers are called (in the order that they have been queued).
但是,如果没有等待处理的UI消息,FMX可能会延迟检查计时器队列!然后,一旦所有UI消息都已处理完毕,在再次处理事件之前可能会有延迟.这完全取决于FMX应用程序的内部状态.
However, if there are no pending UI messages, FMX may delay checking the timer queue! And then once all UI messages have been processed, there may be a delay before events are processed again. It all depends on the internal state of the FMX app.
因此,无法保证1 ms计时器将在1 ms间隔附近的任何地方触发其 OnTimer
事件处理程序.并且这也可以解释为什么UI活动的增加可以使 OnTimer
事件的触发频率更高,因为UI消息的处理频率更高.
So, there is no guarantee whatsoever that a 1 ms timer will fire its OnTimer
event handler anywhere near 1 ms intervals. And it might also explain why an increase in UI activity can allow the OnTimer
event to fire more often, because UI messages are being processed more often.
这与VCL的 TTimer
不同,后者是基于 WM_TIMER
UI消息的,UI消息是低优先级的消息,仅当没有其他UI消息时才生成待办的.生成后,它将直接分派到 TTimer
的内部窗口,而无需进行额外的排队以增加额外的开销层.但是,UI活动的增加会使 TTImer.OnTimer
事件的触发速度变慢,而不是使其加速.
This differs from VCL's TTimer
, which is based on the WM_TIMER
UI message, which is a low-priority message that is only generated when there are no other UI messages pending. And when it is generated, it gets dispatched directly to the TTimer
's internal window, there is no additional queuing involved to add extra layers of overhead. But, an increase in UI activity will slow down the TTImer.OnTimer
event from firing, not speed it up.
对于 TThread.Synchronize()
,只要需要处理待处理的同步请求,它就会主动通知主UI线程,从而允许主UI线程检查并执行同步'ed程序,宜早不宜迟.
In the case of TThread.Synchronize()
, it actively notifies the main UI thread whenever a pending sync request needs to be handled, thus allowing the main UI thread to check for and execute sync'ed procedures sooner rather than later.
这篇关于当手指触摸屏幕时,为什么Android上的Timer更准确?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!