如何同步执行RoboSpice请求?

时间:2014-04-23 11:36:51

标签: robospice

如何同步执行RoboSpice请求?可能吗?我想在IntentService中使用RoboSpice。

编辑:

有时需要同步执行某些操作,例如在服务中。在我最近的项目中,我必须排队一些不同类型的请求,我想将IntentService与RoboSpice一起使用。就我而言,当我执行不同的请求时,我需要等待request1的结果,然后将数据从它传递到request2并执行它。

我想要某种批量请求队列。假设我们有两种类型的请求:request1request2request2需要request1提取的数据:

  1. 执行request1
  2. 等待
  3. 获取request1提取的数据并传递给request2
  4. 执行request2
  5. 等待
  6. 转到1。
  7. 我想使用IntentService(队列)但由于异步而在启动请求后死亡。

    在我看来,使用听众或CountDownLatch并不是最佳方式。

3 个答案:

答案 0 :(得分:7)

根据Riccardo Ciovatti on the RoboSpice mailing list的建议,您问题的直接答案是:

final CountDownLatch latch = new CountDownLatch(1);

final YourRequest request = new YourRequest();
spiceManager.execute(request, new RequestListener<YourResponse>() {

    @Override
    public void onRequestFailure(SpiceException spiceException) {
        latch.countDown();
    }

    @Override
    public void onRequestSuccess(YourResponse response) {
        latch.countDown();
    }
});

latch.await();

但除非它在后台线程上执行,否则这不是一个好用的习惯用法。异步处理是RoboSpice的基本特征;它保持UI线程免费。

答案 1 :(得分:1)

在IntentService中使用RoboSpice。在CountDownLatch的帮助下解决了这个问题。假设我们有2个不同的SpiceManagers和一些syncMethods在IntentService中按顺序执行。

<强>全局

private final SpiceManager aSpiceManager =
       new SpiceManager(ASpiceService.class);
private final SpiceManager bSpiceManager =
       new SpiceManager(BSpiceService.class);

private CountDownLatch handleIntentLatch;

onHandleIntent :在我们执行syncMethodA之前 - 我们用1启动我们的CountDownLatch。执行syncMethodA之后,我们在latch上使用count(相位)来计算countDown()。稍后某些方法会在我们的锁存器上至少调用一次countDown() - 方法onHandleIntent将继续执行并完成,这将触发IntentService onDestroy()回调。

@Override
protected void onHandleIntent(Intent intent) {
    handleIntentLatch = new CountDownLatch(1);

    syncMethodA();

    try {
        handleIntentLatch.await();
    } catch (InterruptedException e) {
        e.printStackTrace();
    }
}

<强> syncMethodA(): 假设我们需要按顺序启动一些同步方法(syncMethodA,回调执行syncMethodB等)。

private void syncMethodA() {
    SpiceRequest requestA = new SpiceRequest();

    if (!aSpiceManager.isStarted()) {
        LogUtils.LOGD(TAG, "starting aSpiceManager");
        aSpiceManager.start(getApplicationContext());
    }

    aSpiceManager.execute(requestA , new RequestListener<ResponseA>() {
        @Override
        public void onRequestSuccess(final ResponseA responseA) {
            // SOME LOGIC

            syncMethodB();

            // SOME LOGIC

        @Override
        public void onRequestFailure(SpiceException spiceException) {
            handleIntentLatch.countDown();
            // SOME LOGIC
        }
    });
}

syncMethodB,syncMethodC等是相同的 - 在 onRequestSuccess 中我们启动下一个syncMethodX。在 onRequestFailure 中,我们countDown()我们的latch(handleIntentLatch)。

非常重要!!! 在最后的syncMethodX顺序中(在完成之后我们希望onHandleIntent方法继续执行并完成将导致IntentService停止) - 我们在 onRequestSuccess 中的countDown()我们的锁存器

onDestroy :在这里我们停止SpinceManagers。

@Override
public void onDestroy() {
    super.onDestroy();
    LogUtils.LOGD(TAG, "onDestroy");
    shutDownSpiceManagers();
}

<强> shutDownSpiceManagers

private void shutDownSpiceManagers() {
    if (aSpiceManager.isStarted()) {
        LogUtils.LOGD(TAG, "stopping aSpiceManager");
        aSpiceManager.shouldStop();
    }
    if (bSpiceManager.isStarted()) {
        LogUtils.LOGD(TAG, "stopping bSpiceManager");
        bSpiceManager.shouldStop();
     }
}

现在一切都应该没问题:没有泄露的上下文,SpiceManagers将在onDestroy中被杀死并且仅在后回调被解决。

答案 2 :(得分:0)

如果您不想完全同步执行,但只希望按顺序按顺序执行请求,您可以编写自己的简单类,只在请求A成功或失败时执行请求B.像那样:https://github.com/Deepscorn/Shared/blob/master/app/src/main/java/com/gamelift/shared/request/base/RequestSequenceExecutor.java。 所以,代码看起来像:

sequenceExecutor.setRequest(new FirstRequest());
sequenceExecutor.setOnSuccessListener(FirstRequest.class, new OnSuccessListener {
   public void onSuccess() {
     sequenceExecutor.setRequest(new SecondRequest());
   }
};

sequenceExecutor.setOnFaulListener(FirstRequest.class, new OnFailListener {
   public void onFail() {
     sequenceExecutor.setRequest(new OnFirstFailRequest());
   }
};

sequenceExecutor.setOnSuccessListener(SecondRequest.class, new OnSuccessListener {
   public void onSuccess() {
     notifyDone();
     return;
   }
};

sequenceExecutor.setDefaultOnFailListener(new OnFailListener {
   public void onFail(Exception e) {
     notifyDone();
     log(e);
     return;
   }
};
sequenceExecutor.execute() //starts execution