猿问

CountDownTimer 在尝试重现声音时冻结 UI

我试图从 3 到 1 每秒再现 beep.wav 声音,例如,再现 3 、 2 和 1 的哔声,然后在完成时再现 beependsound。


出于某种原因,只有 beependsound 正在播放,但是当达到第二个 3 时,ui 似乎冻结了一秒钟,然后数字快速减少到 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();

    }

我认为这可以如上所述工作,有什么提示吗?


杨__羊羊
浏览 141回答 1
1回答

长风秋雁

MediaPlayer.create()可能是一个相当昂贵的电话。考虑一下如果大约需要 100 毫秒(甚至更多)会发生什么:计时器调用onTick()。onTick()内部阻塞约 100 毫秒MediaPlayer.create()。mp开始播放,然后onTick()返回。(到目前为止,一切都很好!)立即,计时器意识到另一个onTick()呼叫到期了!最后一个开始于 100 毫秒前!onTick()几乎立即再次调用。很快,它就接到了stopPlaying()电话。但是您大约在 1 毫秒前才开始玩!这会导致您的计时器将所有时间都花在 中MediaPlayer.create(),而实际上几乎没有时间播放声音。请注意,使用编写的代码,它将尝试在倒计时的最后 3 秒内播放大约 30 次声音(因为理想情况下,滴答声相隔 100 毫秒)。如果您的意图是只播放 3 次声音,您可能希望将第二个if块移动到第一个块内。这样,您仅在secondsLeft实际更改时才尝试播放。这实际上会改善最初的问题,您可能不需要任何进一步的更改。但是如果你想进一步优化,请注意你可以mp提前准备——比如说,当应用程序启动时——然后简单地重复使用它:而不是release()每次都 -ing 它,只是stop()它,prepare()它(而不是&nbsp;reset()它)。这将为下一场比赛做好准备。您甚至可以为 单独创建一个MediaPlayer,beepend并且可以在应用程序初始化期间同时准备它们。
随时随地看视频慕课网APP

相关分类

Java
我要回答