当前位置: 首页 > 知识库问答 >
问题:

在循环中等待事件侦听器?

乐正浩博
2023-03-14

我有一个控制器类,它需要为列表中的每个项目执行各种异步操作:

  • 对于每个A
    • 播放音频并等待完成
    • 等t秒
    • 对于A的每个子部分B:
      • 播放音频并等待
      • 等待t2秒

      当我的OnCompletionListener时,我知道音频是完整的。onCompletion方法被激发,当我的倒计时时,我知道计时器何时完成。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() {
                     ...
             }
           }
         }
      }
      

      但最后我还是无法摆脱内部循环,这让我觉得整个想法都行不通。我已经查看了未来的界面,但这似乎也不是我想要的。

      我知道我可以用一堆变量来解决这个问题,以跟踪我在状态流中的位置,但是带有一些框架的循环会更干净。谢谢:)

共有1个答案

尉迟招
2023-03-14

这种任务听起来像是RxJava的好地方。

请看这篇文章,它向您展示了如何包装MediaPlayer以使用Rx。

我会使用计时器操作符来进行您感兴趣的延迟,并使用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
 类似资料:
  • 我试图制作一个简单的应用程序来学习c(Visual Studio)中的一些东西。现在我正在制作一个音乐播放器,其中一个动作是在按钮点击事件中淡出音乐。 我对构建淡出部分没有问题,我做了一个while循环,每次循环运行时都将音量降低1%。此外,我还使用淡入度值更新标签。 唯一的问题是,为了减缓褪色,我正在使用线程。睡眠事件,该部分将冻结我的应用程序,并阻止使用淡入淡出值对我的文本标签进行任何更新。

  • 我正在Wildfly 9.0.1的KeyClope中配置一个事件侦听器。我创造了一个。jar有两个类,实现了一个提供者,如KeyClope在他的github示例中解释的那样。 在本例中,keydape人员解释说,有必要注册提供者编辑“standalone/configuration/standalone.xml”并将模块添加到providers元素中。我在标签“subsystem”中对这个定义进行

  • 问题内容: 我正在使用bluebird,方法 getAll 和 update return promises。我如何说“等到两个承诺返回,然后更新currentProduct值”?我对JS很陌生… 问题答案: 如果可以使用/,这将很简单。 或者,如果您只能使用简单的承诺,则可以遍历所有产品,并将每个承诺置于最后一个循环中。这样,仅当前一个问题解决时,它才会前进到下一个问题(即使它将首先迭代整个循环

  • 因为这是我的第一篇文章,所以我为它的结构上的任何错误道歉。我正在做一个个人项目,这是一个用java制作的时钟,可以显示时间/日期/日期,每季度播放一个音频文件,以及报时。图形用户界面是用摆动项构建的。 当时钟到达一定时间时,它必须发出钟声/播放声音,我希望在时钟响起时在GUI上显示一个图标。此时,图标在方法的开头切换,在方法的结尾再次切换。在第二次切换图标之前,我希望方法在播放音频时等待()。(也

  • 本文向大家介绍JavaScript 异步等待循环,包括了JavaScript 异步等待循环的使用技巧和注意事项,需要的朋友参考一下 示例 在循环中使用异步等待时,您可能会遇到其中一些问题。 如果您只是尝试在内部使用await forEach,则会抛出Unexpected token错误。 这是因为您错误地将箭头功能视为一个块。该await会在回调函数,这是不是上下文async。 解释器可以防止我们

  • 问题内容: 将html标记中的标准重构为侦听器,我的代码面临问题: 当单击元素时,假定单击的是循环中的最后一个索引,例如Lookslike,仅填充了此循环中的最后一个元素,循环初始化看起来正确,为什么会这样呢? 问题答案: 您需要将事件侦听器的分配包装在闭包中,例如: