У меня есть приложение, которое воспроизводит mp3-файл, и я пытаюсь обновить пользовательское поле синхронно с определенным временем, которое мы записали в таблицу для воспроизведения звука (что-то вроде эффекта караоке). Я использую Handler
, чтобы запланировать эти обновления. В своем классе настраиваемых полей я определяю Runnable
, который должен запускать обновление в нужное время:
private final Runnable mTrigger = new Runnable() {
@Override
public void run() {
int now = mPlayer.getCurrentPosition();
if (mState == STATE_PLAYING && mUpdateAction != null) {
if (mTriggerTime - now > MAX_PREMATURE_TRIGGER) {
// Sound is lagging too much; reschedule this trigger
mHandler.postDelayed(this, mTriggerTime - now);
} else {
// Run the update
mUpdateAction.run();
}
}
}
};
Когда я звоню mPlayer.start()
, я планирую первое обновление, вызывая mHandler.postDelayed(mTrigger, timeToFirstUpdate)
. Каждое действие обновления решает, каким будет следующее обновление, и планирует его (вызывая mHandler.postDelayed(mTrigger, timeToNextUpdate)
). Время обновления обычно составляет несколько сотен миллисекунд.
Проблема в том, что, хотя некоторые обновления происходят быстро в запланированное время, другие могут быть отложены на 200 миллисекунд или более, что весьма заметно для пользователя. Между этими обновлениями я ничего не делаю в своем приложении, кроме воспроизведения звука. (Нет фоновых рабочих потоков; никаких других обновлений дисплея.) Задержки выглядят случайными и каждый раз значительно меняются.
Я не думал, что время для postDelayed
будет таким неточным! Я не знаю, это проблема эмулятора или проблема с моим подходом. Воспроизводит ли звук искажение времени петли потока пользовательского интерфейса? Должен ли я перенести время в фоновый поток (и безопасно ли вызывать mPlayer.getCurrentPosition()
из фонового потока)? Что-то еще?