15

我正在尝试使用 SeekBar 来显示 MediaPlayer 类播放的曲目的长度并在曲目中启用搜索。

在轨道内寻找效果很好。但是,在播放曲目时使用 setProgress 更新进度值似乎会导致轻微的跳过。

在 onCreate 方法中,我创建了一个带有循环的线程,该循环更新当前轨道的 SeekBar 进度值。当轨道改变时,这个循环会重置。

private void createProgressThread() {

    _progressUpdater = new Runnable() {
        @Override
        public void run() {
            //Exitting is set on destroy
            while(!_exitting) {
                _resetProgress = false;
                if(_player.isPlaying()) {
                    try
                    {
                        int current = 0;
                        int total = _player.getDuration();
                        progressBar.setMax(total);
                        progressBar.setIndeterminate(false);

                        while(_player!=null && current<total && !_resetProgress){
                            try {
                                Thread.sleep(1000); //Update once per second
                                current = _player.getCurrentPosition();
                                 //Removing this line, the track plays normally.
                                progressBar.setProgress(current); 
                            } catch (InterruptedException e) {

                            } catch (Exception e){

                            }            
                        }
                    }
                    catch(Exception e)
                    {
                        //Don't want this thread to intefere with the rest of the app.
                    }
                }
            }
        }
    };
    Thread thread = new Thread(_progressUpdater);
    thread.start();
}

理想情况下,我宁愿不使用线程,因为我知道这有缺点。另外请原谅异常吞咽 - 很难继续检查所有 MediaPlayer 状态以响应 UI 事件。但是,我真正的问题是音乐正在跳过。

谁能建议一种替代方法来更新进度并解释为什么即使使用单独的线程,对 setProgress 的调用也会导致轨道跳过?

提前致谢。

4

1 回答 1

27

我认为问题在于,当您调用 setProgress() 时,会触发 onProgressChanged 事件。

监听器 (OnSeekBarChangeListener) 有一个方法 public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser)。在这里,您应该测试侦听器是由用户操作还是由代码触发的。在您的情况下, fromUser 变量应该为 false。

public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) {
    if(fromUser){
           player.seekTo(x);
        }
        else{
         // the event was fired from code and you shouldn't call player.seekTo()
        }
}
于 2011-01-09T20:29:03.607 回答