Using RoboSpice in IntentService. Solved the problem using CountDownLatch. Say we have 2 different SpiceManagers and some syncMethods to execute sequentially in an IntentService.
Globals
private final SpiceManager aSpiceManager = new SpiceManager(ASpiceService.class); private final SpiceManager bSpiceManager = new SpiceManager(BSpiceService.class); private CountDownLatch handleIntentLatch;
onHandleIntent : before executing syncMethodA - we start our CountDownLatch from 1. After executing syncMethodA, we expect () for countDown () on our latch. When later any method calls countDown () on our latch at least once - the onHandleIntent method will continue to execute and complete the execution, which will call the IntentService onDestroy () callback.
@Override protected void onHandleIntent(Intent intent) { handleIntentLatch = new CountDownLatch(1); syncMethodA(); try { handleIntentLatch.await(); } catch (InterruptedException e) { e.printStackTrace(); } }
syncMethodA () : Suppose we need to run some synchronization methods in a sequence (syncMethodA, which calls the syncMethodB callback, etc.).
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) {
syncMethodB, syncMethodC, etc. same - in onRequestSuccess we run the following syncMethodX. In onRequestFailure we count () our latch (handleIntentLatch).
Very important!!! In the last syncMethodX in the sequence (after which we want the onHandleIntent method to continue execution and complete, which will cause the IntentService to stop) - we count () our latch in onRequestSuccess ALSO .
onDestroy : here we stop our Spince managers.
@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(); } }
Now everything should be in order: there is no leak Context, SpiceManagers will be killed in onDestroy AND ONLY AFTER callbacks are allowed.