我有一个控制器类,需要对列表中的每个项执行各种异步操作:
我知道当我的OnCompletionListener.onCompletion
方法被触发时音频已经完成,并且当我的CountDownTimer.onFinish()
方法被触发时我知道计时器何时完成。我试过回复听众:
for (final A a : getAs()) {
show(a);
playAudio(a.audioBegin, new MediaPlayer.OnCompletionListener() {
@Override
public void onCompletion(MediaPlayer mp) {
wait(a.secs, new OnFinishListener() {
@Override
public void onFinish() {
if (a.hasSubparts) {
for (final B b : a.getBs()) {
playAudio(b.audioBegin, new MediaPlayer.OnCompletionListener() {
...
}
}
}
}
但最后我无法摆脱内循环,这让我觉得这整个想法都行不通。我查看了Future
界面,但这似乎也不是我想要的。
我知道我可以用一堆变量来解决这个问题,以便跟踪我在状态流中的位置,但是使用某个框架的循环会更清晰。谢谢:))
答案 0 :(得分:0)
这种任务听起来像是RxJava的好地方。
请查看此post,它会向您展示如何将MediaPlayer包装为使用Rx。
我会使用timer运算符来确定您感兴趣的延迟,并From运算符逐个查看您的列表。
祝你好运
编辑:这是用rxJava做的一种方法,但是这是一个简化版本,一旦你能更好地理解rxJava,你可以稍微好一点,例如包装回调,替换主题机制,处理错误等等上。
所以,首先我们将制作一个可播放对象的平面列表,我假设A和B对象有一个共同的父对象,因为A实际上有更多的方法然后B我假定这个结构:
private interface B {
Object audioBegin();
long getWaitSecs();
}
private interface A extends B {
boolean hasSubparts();
List<B> getBs();
}
所以为了观察播放列表我们会这样做:
//this will create a flat play list
List<B> flatPlayList = new ArrayList<>();
for ( A a : getAs()){
flatPlayList.add(a);
if ( a.hasSubparts()){
for (B b : a.getBs()){
flatPlayList.add(b);
}
}
}
//just creating an observable out of it
Observable<B> playListObservable = Observable.from(flatPlayList);
现在我们有一个播放列表,我们需要一个接一个地播放它,但是等待前一个完成+等待,为此我们将使用一个主题:
//this will be used to inform every time an audio has completed playing after a wait
final PublishSubject<Void> onCompleteSubject = PublishSubject.create();
并一起修补:
//zip will send the next B on the list every time there was an audio completion
Observable.zip(playListObservable, onCompleteSubject, new Func2<B, Void, B>() {
@Override
public B call(B b, Void aVoid) {
return b;
}
}).subscribe(new Action1<B>() {
@Override
public void call(final B b) {
//play the actual audio
playAudio(b.audioBegin(), new MediaPlayer.OnCompletionListener() {
@Override
public void onCompletion(MediaPlayer mp) {
//audio has completed playing, so we will wait sec as needed then infrom that we completed;
Observable.timer(b.getWaitSecs(), TimeUnit.SECONDS).subscribe(new Action1<Long>() {
@Override
public void call(Long aLong) {
onCompleteSubject.onNext(null);
}
});
}
});
}
});
最后,因为第一个项目在完成事件之前不会开始播放,我们只会发送一个来启动整个事件链:
onCompleteSubject.onNext(null); //will cause to start playing