在Android上,postDelayed中的可运行任务何时被执行?

3

我有一段代码中使用了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)输入。看起来延迟的可运行程序被添加到了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();

    }
}

Android 限制在主线程中进行 UI 操作是为了防止你想要做的事情。 - Harlan
@Harlon,我不确定我理解你的意思。 - Maksim Dmitriev
3个回答

2
还有来自其他服务和应用程序的日志,因此基于日志输出计算处理程序延迟将不正确。Android上的记录机制具有自己的队列,因此由于队列中的其他日志,您的消息实际上可能会延迟。
我的建议是使用System.nanoTime()来计算处理程序延迟之间的时间。据我所知,它提供了最精确的计时器值。
最后回答您的问题,不能确定一个操作将发生的确切时间。可能会有数千(如果不是数百万)个不同的条件会延迟您的应用程序的操作,特别是如果它是异步操作。
编辑:该延迟不能保证准确的50毫秒延迟,但可以保证“至少”50毫秒延迟。

是的,看起来 postDelayed(r, 10) 至少保证了 10 毫秒。这里有一个使用 nanoTime 的示例 https://gist.github.com/anonymous/70f301a06959f91b96302d6a6adddd6d - Maksim Dmitriev
07-13 17:58:36.391 30902-30902/sample1.com.sample_1 D/MainActivity: timeHandler = 22583545657183 07-13 17:58:36.281 30902-30902/sample1.com.sample_1 D/MainActivity: beforeTimeHandler = 22583437099224差异为108557959纳秒=10毫秒(大约) - Maksim Dmitriev

1
追踪Handler.postDelay()的代码后,最终调用了MessageQueue.enqueueMessage()。从代码来看,它似乎无限循环遍历消息队列,直到到达末尾或当前任务时间大于延迟时间,然后将任务插入队列中的该位置。这意味着在您想要执行任务的几毫秒内,您的任务应该被执行。我猜测您的操作不是问题所在,而是Android正忙于渲染UI和其他内部工作,这就是延迟您的任务的原因。可以推测,在您的postDelay时间+10ms之前,已经排队执行了活动及其扩展类中的onCreateonStartonResume中的所有代码。

100毫秒大约是6帧,因此可能仅是显示活动UI所需的时间,请尝试在按钮点击上执行您的postDelay,我相信时间会更可预测,因为UI和Activity没有被设置或拆除。


07-13 17:49:45.781 14332-14332/sample1.com.sample_1 D/MainActivity: i = 0.....07-13 17:49:45.871 14332-14332/sample1.com.sample_1 D/MainActivity: postDelayed看起来将代码移到按钮点击事件中并没有任何区别。 - Maksim Dmitriev

0

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接