CountDownTimer останавливает пользовательский интерфейс при попытке воспроизвести звук - PullRequest
0 голосов
/ 11 февраля 2019

Я пытаюсь воспроизводить звук beep.wav каждую секунду от 3 до 1, например, воспроизводить 3, 2 и 1 звуковой сигнал, а затем по окончании воспроизводить beependsound.

Дляпо какой-то причине воспроизводится только beependsound, но при достижении второй 3 кажется, что пользовательский интерфейс зависает на секунду, а затем цифры быстро уменьшаются до 0

private void stopPlaying(){
        if(mp!=null){
            try {
                mp.reset();
                mp.prepareAsync();
                mp.stop();
                mp.release();
                mp=null;
            }
            catch (Exception e)
            {
                e.printStackTrace();
            }
        }
    }

    private void startCountDown() {

        aCounter = new CountDownTimer(10000, 100) {
            public void onTick(long millisUntilFinished) {


                if (Math.round((float) millisUntilFinished / 1000.0f) != secondsLeft) {
                    countDownTxt.setTextColor(getResources().getColor(R.color.white));
                    secondsLeft = Math.round((float) millisUntilFinished / 1000.0f);
                    countDownTxt.setText(String.valueOf(secondsLeft));
                }

                if (secondsLeft <= 3) {
                    countDownTxt.setTextColor(getResources().getColor(R.color.colorAccent));
                    stopPlaying();
                    mp = MediaPlayer.create(MainActivity.this, R.raw.beep);
                    mp.start();
                }
            }

            public void onFinish() {
                secondsLeft = 0;
                stopPlaying();
                mp = MediaPlayer.create(MainActivity.this, R.raw.beepend);
                mp.start();
                final Handler handler = new Handler();
                handler.postDelayed(new Runnable() {
                    @Override
                    public void run() {
                        aCounter.cancel();
                        startCountDown();
                    }
                }, 1000);

            }
        };
        aCounter.start();
    }

Я пытаюсь работать так, как описано выше, любой намек?

1 Ответ

0 голосов
/ 12 февраля 2019

MediaPlayer.create() может быть довольно дорогим звонком.Подумайте, что произойдет, если это займет примерно 100 мс (или даже больше):

  1. Таймер вызывает onTick().
  2. onTick() блоков в течение примерно 100 мс внутри MediaPlayer.create().
  3. mp начинает играть, а onTick() возвращается.(Пока все хорошо!)
  4. Немедленно таймер понимает, что еще один onTick() вызов подлежит!Последний начался более 100 мс назад!
  5. onTick() вызывается снова, почти сразу.Очень быстро он достигает звонка stopPlaying().Но вы только начали , играя около 1 мс назад!

Это приводит к ситуации, когда ваш таймер тратит все свое время на MediaPlayer.create(), и практически не играет времени за воспроизведение звука.

Обратите внимание, что при написанном коде он будет пытаться воспроизвести звук приблизительно 30 раз за последние 3 секунды обратного отсчета (поскольку такты в идеале находятся на расстоянии 100 мс).Если ваше намерение состояло в том, чтобы воспроизвести звук только 3 раза, вы можете переместить второй блок if внутрь первого.Таким образом, вы пытаетесь играть, только когда secondsLeft действительно изменяется.Это на самом деле улучшит исходную проблему, и вам, возможно, не понадобятся дальнейшие изменения.

Но если вы хотите оптимизировать дальше, учтите, что вы можете подготовить mp заранее - скажем, при запуске приложения- и просто используйте его снова: вместо release() - каждый раз, просто stop() и prepare()не reset() это).Это оставит это готовым к следующей игре.Вы даже можете создать отдельный MediaPlayer только для beepend и подготовить их оба во время инициализации приложения.

...