为了账号安全,请及时绑定邮箱和手机立即绑定

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

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

杨__羊羊 2022-06-15 09:43:32
我试图从 3 到 1 每秒再现 beep.wav 声音,例如,再现 3 、 2 和 1 的哔声,然后在完成时再现 beependsound。出于某种原因,只有 beependsound 正在播放,但是当达到第二个 3 时,ui 似乎冻结了一秒钟,然后数字快速减少到 0private 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 回答

?
长风秋雁

TA贡献1757条经验 获得超7个赞

MediaPlayer.create()可能是一个相当昂贵的电话。考虑一下如果大约需要 100 毫秒(甚至更多)会发生什么:

  1. 计时器调用onTick()

  2. onTick()内部阻塞约 100 毫秒MediaPlayer.create()

  3. mp开始播放,然后onTick()返回。(到目前为止,一切都很好!)

  4. 立即,计时器意识到另一个onTick()呼叫到期了!最后一个开始于 100 毫秒前!

  5. onTick()几乎立即再次调用。很快,它就接到了stopPlaying()电话。但是您大约在 1 毫秒前才开始玩!

这会导致您的计时器将所有时间都花在 中MediaPlayer.create(),而实际上几乎没有时间播放声音。

请注意,使用编写的代码,它将尝试在倒计时的最后 3 秒内播放大约 30 次声音(因为理想情况下,滴答声相隔 100 毫秒)。如果您的意图是只播放 3 次声音,您可能希望将第二个if块移动到第一个块内。这样,您仅在secondsLeft实际更改时才尝试播放。这实际上会改善最初的问题,您可能不需要任何进一步的更改。

但是如果你想进一步优化,请注意你可以mp提前准备——比如说,当应用程序启动时——然后简单地重复使用它:而不是release()每次都 -ing 它,只是stop()它,prepare()它(而不是 reset()它)。这将为下一场比赛做好准备。您甚至可以为 单独创建一个MediaPlayerbeepend并且可以在应用程序初始化期间同时准备它们。


查看完整回答
反对 回复 2022-06-15
  • 1 回答
  • 0 关注
  • 140 浏览

添加回答

举报

0/150
提交
取消
微信客服

购课补贴
联系客服咨询优惠详情

帮助反馈 APP下载

慕课网APP
您的移动学习伙伴

公众号

扫描二维码
关注慕课网微信公众号