robospice icon indicating copy to clipboard operation
robospice copied to clipboard

Question: how to execute a robospice synchronously?

Open PerfectCarl opened this issue 11 years ago • 22 comments

I'm using robospice on a project that already has an async execution infrastructure. For the moment, I don't want to refactor all my code, but just start using robospice for its nice Api and built in cache.

So I would need to execute the execute method synchronously. Is it possible ? Can I wait on a requestlistener ?

PerfectCarl avatar Feb 12 '14 20:02 PerfectCarl

Maybe in your instance you need to try and use the RequestRunner class on it's own.

Take a look to see if the required parameters are available to you

On 12 February 2014 20:39:43 GMT, PerfectCarl [email protected] wrote:

I'm using robospice on a project that already has an async execution infrastructure. For the moment, I don't want to refactor all my code, but just start using robospice for its nice Api and built in cache.

So I would need to execute the execute method synchronously. Is it possible ? Can I wait on a requestlistener ?


Reply to this email directly or view it on GitHub: https://github.com/octo-online/robospice/issues/265

Sent from my Android phone with K-9 Mail. Please excuse my brevity.

softwaremaverick avatar Feb 13 '14 08:02 softwaremaverick

I feel like I should write a requestrunner that wouldn't use the service to execute the request (but still be a nice robospice citizen to enjoy the caching services).

At the core, my use case is about using robospice as a back end for a data adapter for a viewpager. Maybe you have sample of code for this.

That way I could scrap the async data adapter that I wrote (inspired by cwac) and start from your sample... Le 13 févr. 2014 09:51, "softwaremaverick" [email protected] a écrit :

Maybe in your instance you need to try and use the RequestRunner class on it's own.

Take a look to see if the required parameters are available to you

On 12 February 2014 20:39:43 GMT, PerfectCarl [email protected] wrote:

I'm using robospice on a project that already has an async execution infrastructure. For the moment, I don't want to refactor all my code, but just start using robospice for its nice Api and built in cache.

So I would need to execute the execute method synchronously. Is it possible ? Can I wait on a requestlistener ?


Reply to this email directly or view it on GitHub: https://github.com/octo-online/robospice/issues/265

Sent from my Android phone with K-9 Mail. Please excuse my brevity.

Reply to this email directly or view it on GitHubhttps://github.com/octo-online/robospice/issues/265#issuecomment-34958827 .

PerfectCarl avatar Feb 13 '14 12:02 PerfectCarl

Hi,

Unless I'm very much mistaken the request runner doesn't use the service itself but some dependent classes.

The Default Request Runner class seems to require an executor which I haven't clarified what that entails.

If it can't entirely suffice then maybe the request runner could be split into more methods that would then suffice.

On 13 February 2014 12:33:34 GMT, PerfectCarl [email protected] wrote:

I feel like I should write a requestrunner that wouldn't use the service to execute the request (but still be a nice robospice citizen to enjoy the caching services).

At the core, my use case is about using robospice as a back end for a data adapter for a viewpager. Maybe you have sample of code for this.

That way I could scrap the async data adapter that I wrote (inspired by cwac) and start from your sample... Le 13 févr. 2014 09:51, "softwaremaverick" [email protected] a écrit :

Maybe in your instance you need to try and use the RequestRunner class on it's own.

Take a look to see if the required parameters are available to you

On 12 February 2014 20:39:43 GMT, PerfectCarl [email protected] wrote:

I'm using robospice on a project that already has an async execution infrastructure. For the moment, I don't want to refactor all my code, but just start using robospice for its nice Api and built in cache.

So I would need to execute the execute method synchronously. Is it possible ? Can I wait on a requestlistener ?


Reply to this email directly or view it on GitHub: https://github.com/octo-online/robospice/issues/265

Sent from my Android phone with K-9 Mail. Please excuse my brevity.

Reply to this email directly or view it on GitHubhttps://github.com/octo-online/robospice/issues/265#issuecomment-34958827 .


Reply to this email directly or view it on GitHub: https://github.com/octo-online/robospice/issues/265#issuecomment-34973879

Sent from my Android phone with K-9 Mail. Please excuse my brevity.

softwaremaverick avatar Feb 13 '14 18:02 softwaremaverick

@stephanenicolas please give your opinion on this im stucked here too

eefret avatar Apr 23 '14 16:04 eefret

@eefret if you are stuck on this you could simply use a CountDownLatch to await.

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();

rciovati avatar Apr 23 '14 20:04 rciovati

Great answer, Ricc !

I would have struggled against the idea of sync request processing. I don't see a use case, and find it quite dangerous to block the ui thread, but your solution is what @eefret asked for.

S.

2014-04-23 22:26 GMT+02:00 Riccardo Ciovati [email protected]:

@eefret https://github.com/eefret if you are stuck on this you could simply use a CountDownLatch to await.

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();

— Reply to this email directly or view it on GitHubhttps://github.com/stephanenicolas/robospice/issues/265#issuecomment-41210293 .

stephanenicolas avatar Apr 24 '14 07:04 stephanenicolas

@rciovati great answer. Just for the sake of completion, I ended up modifying my code to use the full async robospice architecture.

PerfectCarl avatar Apr 24 '14 08:04 PerfectCarl

Good choice @PerfectCarl. Non blocking the UI Thread is really a better design.

S.

2014-04-24 10:28 GMT+02:00 PerfectCarl [email protected]:

@rciovati https://github.com/rciovati great answer. Just for the sake of completion, I ended up modifying my code to use the full async robospice architecture.

— Reply to this email directly or view it on GitHubhttps://github.com/stephanenicolas/robospice/issues/265#issuecomment-41255442 .

stephanenicolas avatar Apr 24 '14 08:04 stephanenicolas

@stephanenicolas May I provide such a use case?

Suppose you have an Adapter whose values are obtained from the network. So, you override the Adapter's Filter.performFiltering() and execute a network request there. Since performFiltering() is executed by the system in a non-UI thread, you can execute a synchronous network request. Actually, you MUST execute a synchronous request, because performFiltering() has to return the results. And if you explicitly call your request's loadDataFromNetwork(), you lose all the benefits of the caching/retrying/etc mechanisms.

For the moment, @rciovati 's brilliant solution will do just fine! It could probably be used as a basis for a synchronous SpiceManager.execute() as well...

gkylafas avatar Jun 04 '14 14:06 gkylafas

There's other cases too, for example if you have an app that requires a server configuration to construct your UI by a Subscription Setting, then you need to block the UI (SplashScreen or something) until the data has been loaded. @rciovati Solution worked perfectly, Thanks.

eefret avatar Jun 06 '14 15:06 eefret

Hi all,

I close the thread as I don't think there is anything more to add to @rciovati 's answer.

Please ask questions on the mailing list more than on github, though this topic was interesting.

stephanenicolas avatar Jun 11 '14 04:06 stephanenicolas

I invite you guys to submit a PR. It could be easy to return a request status in a new synchronous method based on @rciovati's implementation :

public RequestResult executeSynchronously(SpiceRequest request) public RequestResult executeSynchronously(SpiceRequest request, Object cacheKey, long cacheExpiry) public RequestResult executeSynchronously(SpiceRequest request, long timeout) public RequestResult executeSynchronously(SpiceRequest request, Object cacheKey, long cacheExpiry, long timeout)

Where RequestResult could provide either the result, an exception, including a new timeout exception.

Volunteers ? (Don't forget tests and squash into a single commit before publishing the PR !)

Stéphane

2014-06-06 17:49 GMT+02:00 Christopher Herrera [email protected]:

There's other cases too, for example if you have an app that requires a server configuration to construct your UI by a Subscription Setting, then you need to block the UI (SplashScreen or something) until the data has been loaded. @rciovati https://github.com/rciovati Solution worked perfectly, Thanks.

— Reply to this email directly or view it on GitHub https://github.com/stephanenicolas/robospice/issues/265#issuecomment-45352177 .

stephanenicolas avatar Jun 14 '14 17:06 stephanenicolas

I will do it this week :-)

rciovati avatar Jun 14 '14 18:06 rciovati

Cool. But we could let this one to others... Wdyt? Le 14 juin 2014 20:52, "Riccardo Ciovati" [email protected] a écrit :

I will do it this week :-)

— Reply to this email directly or view it on GitHub https://github.com/stephanenicolas/robospice/issues/265#issuecomment-46096414 .

stephanenicolas avatar Jun 14 '14 19:06 stephanenicolas

Ok, if there is any voluntary leave it to him :-)

rciovati avatar Jun 15 '14 08:06 rciovati

Well, not yet apparently but I see this enhancement as very feasible and it could be turned into an opportunity to give more space to others and empower the community of RS users.

Nevertheless, I would like to code it myself too and clearly understand your motivation ;) I don't wanna refrain you from contributing to RS, Ricc.

My point was just to tell you it could be an opportunity to make other people contribute to RS, but that's my only point, no obligation.

Indeed, can I let you take that issue in charge, and decide how to solve it, either by hoping others to volunteer or to do it by yourself ?

If you agree, just assign it to you, I don't wanna interfere any more, I already hope not have discouraged you ;)

Stéphane Le 15 juin 2014 10:26, "Riccardo Ciovati" [email protected] a écrit :

Closed #265 https://github.com/stephanenicolas/robospice/issues/265.

— Reply to this email directly or view it on GitHub https://github.com/stephanenicolas/robospice/issues/265#event-131486504.

stephanenicolas avatar Jun 15 '14 09:06 stephanenicolas

I have had a use case for this in a project and used @rciovati's solution. Maybe it would be a good starter for me!? ETA would also be somewhere next week.

nkeskinov avatar Jun 15 '14 16:06 nkeskinov

I let you @nkeskinov and @rciovati decide who does what. Maybe we could start using feature branches and submit PRs for reviews between us, contributors ? I let you guys see how you collaborate on this.

stephanenicolas avatar Jun 15 '14 16:06 stephanenicolas

After a small investigation on this one, it looks to me like it is not as simple as on first sight. Problem seems to be that if we await() from the main thread (since we usually call execute() there), then calling countDown() from RequestListener's methods, also executed on the main thread, is never going to work.

It seems that all the use cases that were using this way of synchronous execution were actually calling execute() from a non-main thread.

Therefore, a complete solution for this would require another implementation of com.octo.android.robospice.request.notifier.RequestListenerNotifier (other than DefaultRequestListenerNotifier) which is going to use a Handler from some other thread. Or any other idea the involved people may have :)

nkeskinov avatar Jun 17 '14 18:06 nkeskinov

Would see if I can get a good idea for this, I had to hack workarounds in some of my projects.

eefret avatar Mar 25 '15 19:03 eefret

The simplest might be to use a countdownlatch inside your listener.

Beware of freezing the UI thread though...

2015-03-25 12:56 GMT-07:00 Christopher Herrera [email protected]:

Would see if I can get a good idea for this, I had to hack workarounds in some of my projects.

— Reply to this email directly or view it on GitHub https://github.com/stephanenicolas/robospice/issues/265#issuecomment-86193740 .

stephanenicolas avatar Mar 25 '15 19:03 stephanenicolas

when I define a CountDownLatch outside the SpiceManager::execute() call, and call countDown() inside onRequestFailure() as well as in onRequestFailure(), the UI halts... as if execute() never returns... so how can that be a good solution? (I'm using com.octo.android.robospice:robospice-spring-android:1.4.14) (see https://github.com/stephanenicolas/robospice/issues/265#issuecomment-41251811)

axd1967 avatar Jul 13 '15 12:07 axd1967