我正在尝试每秒从3到1再现beep.wav声音,例如,再现3、2和1的哔声,然后在完成时再现哔声。
由于某种原因,只有蜂鸣声正在播放,但是当到达第二秒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();
}
我认为它可以如上所述工作,有什么提示吗?
答案 0 :(得分:1)
MediaPlayer.create()
可能是一个非常昂贵的电话。考虑一下如果花费大约100毫秒(甚至更多)会发生什么:
onTick()
。onTick()
在MediaPlayer.create()
内部阻塞约100毫秒。mp
开始播放,然后onTick()
返回。 (到目前为止,太好了!)onTick()
通话到期了!最后一个开始于100毫秒前!onTick()
几乎立即被再次调用。很快,它到达了stopPlaying()
调用。但是您只有开始在大约1毫秒前播放!这会导致您的计时器将所有时间都花在MediaPlayer.create()
上,而实际上没有时间播放声音。
请注意,在编写代码的情况下,它将在倒数的最后3秒内尝试播放声音大约30次(因为刻度线之间最好间隔100毫秒)。如果您打算只播放声音3次,则可能需要将第二个if
块移到第一块的内部。这样,您仅在secondsLeft
实际更改时尝试播放。这实际上将改善原始问题,并且您可能不需要任何进一步的更改。
但是,如果您想进一步优化,请注意,您可以预先准备mp
(例如,在应用启动时)并简单地重用它:而不是release()
-对其进行分别时间,只需stop()
和prepare()
(并且不要 reset()
)。这样就可以为下一场比赛做好准备了。您甚至可以仅为MediaPlayer
创建一个单独的beepend
,并且可以在应用初始化期间同时准备它们。