stephanenicolas / robospice

Repo of the Open Source Android library : RoboSpice. RoboSpice is a modular android library that makes writing asynchronous long running tasks easy. It is specialized in network requests, supports caching and offers REST requests out-of-the box using extension modules.
Apache License 2.0
2.95k stars 545 forks source link

Runtime URL change - how to? #401

Open mgrzechocinski opened 9 years ago

mgrzechocinski commented 9 years ago

Hey,

In my app I need to allow tester to switch server URL on the login activity. Once URL is changed, app should use it in every later requests. Seem pretty straightforward but...

RoboSpiceService starts for the very first time when I call spiceManager.start(Context). Once it's started, it creates a restAdapter instance (I'm using Retrofit module), so it has it's URL set. Now, when I change URL in a dialog, I try to reload RoboSpiceService calling spiceManager.shouldStop() and spiceManager.start(Context) one after another.

Generally it works, but sometimes does not. The problem is that sometimes the service doesn't catch up with destroying itself, so it only stops&starts again (onStop and onStart method are called). Since restadapter is constructed in onCreate method, and it is not always called, my app still uses the outdated version of restAdapter and, therefore, uses outdated URL.

Since I know my requirement of changing URL in runtime is rather unusual I have a philosophical question how you guys would handle such a situation? How would you force RoboSpice to reload it's serivce and, therefore, RestAdapter?

Thanks in advance for any hints

nkeskinov commented 9 years ago

Hi Mateusz,

I would implement a custom SpiceService similar to com.octo.android.robospice.retrofit.RetrofitSpiceService, which would offer the "dynamicity" you require. You can, for example, store a retrofit.RestAdapter.Builder instead of a RestAdapter field and reset it on every change of the serverUrl.

Hope this helps.

Regards, Nikola

mgrzechocinski commented 9 years ago

Thanks for such a quick response :)

Actually, what you propose is exactly what I'm coding right. I'm not convinced of the way I solve this, though. I don't like the fact I call stop&start spice manager, it's an overhead.

The question is how to communicate with a SpiceService instance so I can ask it: Ok, reload please. I'm wondering about introducing my own type of request, with injected SpiceService instance which executes it, and then just call a method like reloadUrl? Sounds good?

nkeskinov commented 9 years ago

Actually, I now think it's better to resolve this on Retrofit level. You can provide a retrofit.Endpoint with the retrofit.RestAdapter.Builder#setEndpoint(retrofit.Endpoint) and this (possibly singleton) object will provide the URL at the time of HTTP execution (see retrofit.RestAdapter.RestHandler#invokeRequest).

If you make your endpoint singleton, you will be able to easily manipulate the server URL on demand and the change will apply immediately.

The only challenge left is the inflexible RetrofitSpiceService (I agree it should be revised). You should just extend the com.octo.android.robospice.retrofit.RetrofitSpiceService#createRestAdapterBuilder method and provide a retrofit.RestAdapter.Builder that is going to use that dynamic retrofit.Endpoint.