2016-07-13 10 views
3

Существует фрагмент кода, в котором я использую postDelayed и некоторый другой код, выполняемый в основном потоке. Я побежал его несколько раз, и всегда видел следующий вывод:Когда runnables отправлены в postDelayed, фактически исполняемые на Android?

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

.. ..

07-13 14: 22: 18,601 15376-15376/sample1.com.sample_1 Д/MainActivity: onResume 07-13 14: 22: 18,601 15376-15376/sample1.com.sample_1 Д/MainActivity : postDelayed

As I см. из выхода журнала, не имеет значения, что моя задержка составляет 50 мс. Сообщение «postDelayed» вводится после примерно 100 мс (601-511 = 90). Похоже, что замедленная runnable добавлена ​​в конец очереди сообщений моего потока пользовательского интерфейса. Но так или иначе, есть ли какая-либо гарантия того, когда набирается именно 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(); 

    } 
} 
+0

Android ограничивает работу пользовательского интерфейса в основном потоке, чтобы предотвратить то, что вы хотите сделать. – Harlan

+0

@ Харлон, я не уверен, что понял тебя. –

ответ

2

Также имеются журналы других служб и приложений, поэтому вычисление задержки обработчика на основе выходных данных журнала будет неправильным. Механизм регистрации на Android имеет свою собственную очередь, поэтому ваше сообщение может быть отложено из-за других журналов в очереди.

Мое предложение будет использовать System.nanoTime(), чтобы рассчитать промежуток времени между обработчиками. Насколько я знаю, это дает самое точное значение таймера.

Наконец, чтобы ответить на ваш вопрос, вы не можете точно определить точное время, когда действие будет выполнено. Существуют тысячи (если не миллионы) разных условий, которые могут задерживать действия вашего приложения, особенно если это асинхронное действие.

Редакция: Эта задержка не может гарантировать ровно 50 мс задержки, но она может гарантировать «минимум 50 мс».

+0

Да, похоже, что 'postDelayed (r, 10)' гарантирует _at минимум_ 10 мс. Вот пример с nanoTime https://gist.github.com/anonymous/70f301a06959f91b96302d6a6adddd6d –

+0

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 nanosec = 10 мс (приблизительно) –

0

использование post() фактически называют sendMessageDelayed(getPostMessage(r), 0) и postDelayed() будем называть sendMessageDelayed(getPostMessage(r), delayMillis), они похожи.

в post...() методы, в конечном счете называют queue.enqueueMessage, разные по when парам, он решает, где тзд будет вставлен в очередь сообщений. вы можете изменить msg в очереди, но не можете прервать выполнение msg.

1

После отслеживания кода для Handler.postDelay() вниз, похоже, что в конце концов вызывается MessageQueue.enqueueMessage(). Из кода, кажется, бесконечно цикл через очередь сообщений до тех пор, пока он не достигнет конца или пока текущее время задач не будет выше нашего времени задержки, а затем введет задачу в эту позицию в очереди. Это означает, что очередь впереди, где выполняется ваша задача, занимает очень много времени, вы должны больше выполнять свою задачу за несколько миллисекунд, когда захотите.

Я предполагаю, что ваши действия не являются проблемой, но Android занят основным потоком, отображающим ваш пользовательский интерфейс и другие внутренние задания, что и задерживает вашу задачу. Предположительно, выполнение всего кода в onCreate, onStart, onResume о вашей деятельности и расширениях классов было поставлено в очередь до вашего postDelay time + 10ms.

100 мс - это примерно 6 кадров, поэтому может потребоваться время, чтобы отобразить пользовательский интерфейс вашей деятельности, попробуйте выполнить свой postDelay нажатием кнопки вместо этого, я считаю, что время будет намного более предсказуемым, так как пользовательский интерфейс и активность не устанавливаются и не срываются.

+0

07-13 17: 49: 45,781 14332-14332/sample1.com.sample_1 D/MainActivity: я = 0 ..... 07-13 17: 49: 45,871 14332-14332/sample1.com.sample_1 D/MainActivity: postDelayed похоже, переместив код кнопки мыши не имеет никакого значения –