何时在postDelayed上发布的runnables实际上是在Android上执行的?

时间:2016-07-13 11:27:18

标签: android android-handler postdelayed

有一段代码我使用postDelayed和主线程上执行的其他一些代码。我跑了几次,总是看到以下输出:

  

07-13 14:22:18.511 15376-15376 / sample1.com.sample_1 D / MainActivity:i   = 0

     

...

     

07-13 14:22:18.601 15376-15376 / sample1.com.sample_1 D / MainActivity:   onResume 07-13 14:22:18.601 15376-15376 / sample1.com.sample_1   D / MainActivity:postDelayed

从日志输出中可以看出,延迟时间为50毫秒并不重要。消息" postDelayed"在大约100毫秒(601-511 = 90)之后键入。看起来延迟的runnable被添加到我的UI线程的消息队列的末尾。但无论如何,是否有关于何时输入postDelayed的保证?它可以在for循环的中间输入吗?

package sample1.com.sample_1;

import android.os.Bundle;
import android.os.Handler;
import android.support.v7.app.AppCompatActivity;
import android.util.Log;

public class MainActivity extends AppCompatActivity {


    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        new Handler().postDelayed(new Runnable() {
            @Override
            public void run() {
                Log.d("MainActivity", "postDelayed");
            }
        }, 10);
        for (int i = 0; i < 10000; i++) {
            Log.d("MainActivity", "i = " + i);
        }
    }

    @Override
    protected void onResume() {
        Log.d("MainActivity", "onResume");
        super.onResume();

    }
}

3 个答案:

答案 0 :(得分:2)

还有来自其他服务和应用程序的日志,因此根据日志输出计算Handler延迟将不正确。 Android上的日志记录机制有自己的队列,因此您的消息实际上可能因队列中的其他日志而延迟。

我的建议是使用System.nanoTime()来计算处理程序延迟之间的时间。据我所知,它提供了最精确的计时器值。

最后要回答你的问题,不能指出行动发生的确切时间。有数千个(如果不是数百万个)不同的条件可能会延迟应用程序的操作,特别是如果它是异步操作。

编辑:这种延迟不能保证恰好50ms延迟,但它可以保证至少&#34;至少&#34; 50ms延迟。

答案 1 :(得分:1)

跟踪Handler.postDelay()的代码后,看起来最终会调用MessageQueue.enqueueMessage()。从代码中,它似乎无限循环遍历消息队列,直到它到达结束或直到当前任务时间高于我们的延迟时间,然后将任务插入到队列中的该位置。这意味着执行任务之前的队列花费的时间非常长,您应该在几毫秒内执行任务。

我猜你的操作不是问题,而是Android忙于主线程渲染你的UI和其他内部工作,这就是推迟你的任务。据推测,执行活动中onCreateonStartonResume的所有代码及其扩展的类在postDelay时间+ 10ms之前排队。

100ms大约是6帧,所以它可能只是显示你的活动的UI所花费的时间,尝试在按钮点击上执行你的postDelay,我相信时间会更加可预测,因为UI和Activity不是正在安装或拆除。

答案 2 :(得分:0)

使用post()实际调用sendMessageDelayed(getPostMessage(r), 0)postDelayed()将调用sendMessageDelayed(getPostMessage(r), delayMillis),它们类似。

post...()方法最终将调用queue.enqueueMessagewhen param不同,它决定将msg插入消息队列的位置。你可以改变队列中的msg,但不能中断msg的运行。