我目前正在构建一个在wifi扬声器上播放音乐的应用。该应用程序可以连接到多个扬声器,每个扬声器播放不同的音乐。
由于接收扬声器发送到应用程序的歌曲播放进度经常丢失,我必须为正在播放音乐的每个扬声器运行一个计时器,以便持续跟踪歌曲进度。因此,每次收到歌曲进度时,我都会更新计时器,然后计时器将从更新的歌曲进度开始计数。
这是运行计时器的代码。
public class SongTimer
{
Timer mTimer;
int count;
long duration;
int groupAddress;
SongTimerListener listener;
boolean timer;
private Handler mHandler = new Handler();
public interface SongTimerListener
{
public void onPositionCounted(int position);
public void onFinishCounting();
}
public SongTimer(int position, long duration, int groupAddress, SongTimerListener listener)
{
this.listener = listener;
this.count = position;
this.duration = duration;
this.groupAddress = groupAddress;
timer = true;
}
public void startTimer()
{
mTimer = new Timer();
mTimer.schedule(new TimerTask()
{
@Override
public void run()
{
if (timer)
{
if(count<=(duration/1000))
{
mHandler.post(new Runnable()
{
public void run(){
if (DataHolder.PlayProgress.containsKey(DataHolder.tSpeaker.mAddress))
{
long progress = DataHolder.PlayProgress.get(DataHolder.tSpeaker.mAddress);
count=(int)progress;
}
}
});
}
else
{
mHandler.post(new Runnable()
{
public void run()
{
count = 0;
}
});
}
}
else
{
mHandler.post(new Runnable()
{
public void run()
{
mTimer.cancel();
mTimer = null;
if(SongTimer.this.listener != null)
{
SongTimer.this.listener.onFinishCounting();
}
}
});
}
count++;
if(SongTimer.this.listener != null)
{
SongTimer.this.listener.onPositionCounted(count);
}
}
}, 1000, 1000);
}
public void stopTimer()
{
timer = false;
DataHolder.PlayProgress.put(this.groupAddress, (long)count);
}
}
用户选择扬声器,然后当用户使用扬声器播放音乐时,将启动一个计时器。当用户切换到另一个扬声器并用它播放一首歌时,将再次启动一个新的计时器。所有已启动的计时器都将使用 groupAddress 作为对象的计时器存储在HashMap
中。
当用户点击暂停时,将从HashMap
获取计时器然后终止计时器,但会记住计算的最后一个位置。
当用户点击恢复时,将再次开始计时(新的计时器()),然后从存储的最后一个位置开始计数。
问题出现了:
当多个计时器开始运行时,它们运行正常。但是当用户点击暂停时,将从HashMap中获取一个计时器,然后终止它。但不幸的是,所有计时器都在同一时间终止。我检查了Log的定时器的对象ID,它们都是不同的。所以我不明白这里有什么问题。
请帮忙。非常感谢!
答案 0 :(得分:1)
尝试这个
public class SongTimer{
int count;
long duration;
int groupAddress;
SongTimerListener listener;
boolean timer,run;
View user; //the view who this is going to be attached to
public interface SongTimerListener {
public void onPositionCounted(int position);
public void onFinishCounting();
}
//your constructor
public SongTimer(int position, long duration, int groupAddress,
SongTimerListener listener, View viewToAttach){ //added new parameter
this.listener = listener;
this.count = position;
this.duration = duration;
this.groupAddress = groupAddress;
timer = run = true;
user = viewToAttach;
new Thread(new Runnable() { // your timer
@Override
public void run() {
while(run){
if(!timer)
continue;
//now add your implementation here, (its too late here)
//put your code that you already have here, but minor changes
//if you need to call a Ui method use the user.post(runnable); it
// the same as handler.post(runnable), also with this you have
// reference to your view to which you want to alter, so all you
// to do is do what you want to do easily without actually needing
// your interface call. and all Views that they rely on the music
//mechanism that you talked about will each have an instance of this
//class. your pausing mechanism has already being implemented so
//maintain your old pausing mechanism. Also if you are done and want
// totally stop the thread or kill this class set the boolean run
//variable to false.
}
}).start();
}
希望有所帮助