-
Notifications
You must be signed in to change notification settings - Fork 545
Advanced RoboSpice Usages and FAQ
This page is dedicated to explain advanced RoboSpice usages and answer frequently asked questions
Since 1.4.13, RS is officially compatible from SDK 10+. We drop support for SDK 8 & 9. Though a "best effort" help will be provided to/by the community. The main cause is that Android emulator < 10 is not available anymore, thus we lost CI testing capacity and can't guarantee test passing anymore.
Before 1.4.13, RS is compatible with your granpa's phone : SDK 8+.
Yes, override SpiceService.getThreadCount()
to change the number of threads used to process requests. Defaults to 1.
This question may have 2 meanings :
- if you are talking about the Thread priority of threads used to process requests, you can override
SpiceService.getThreadPriority()
to change the priority of threads used to process requests. Defaults toThread.MIN_PRIORITY
. - if you are talking about requests themselves, you can assign each request a priority inside RoboSpice by invoking
spiceRequest.setPriority()
. RS will do its best to execute first all high priority requests.
Use spiceRequest.setRetryPolicy()
. By default, requests have a DefaultRetryPolicy
. It will be activated when a network request fails.
You can cancel a pending request by either
- using the request object itself and cancelling it by invoking
cancel()
- cancelling a request using its cache key and result type via the
spiceManager.cancel()
method. This is preferred as the cache key can be saved in the onSaveInstanceState bundle.
The first mechanism is hard to put it place on Android as you can loose a request object very easily (during a rotation for instance) but can still be considered in some simple cases (where rotation is blocked for instance).
The SpiceManager
will let you add a listener to a request if such a request exists by using :
spiceManager.addListenerToPendingRequest
This will not execute any request, just add a listener to a potentially pending request. If no such request exists, it won't do anything, but if you use PendingRequestListener
, then you will be notified of this "miss".
Use spiceManager.getDataFromCache()
using the result type and the cache key as a compound key to identify request's result in the cache.
InFileObjectPersister.setKeySanitizer()
can be used to provide a bijective key sanitation. We provide a default implementation : DefaultKeySanitizer
class can be used out of the box.
The core of RoboSpice is dedicated to networking but no to HTTP. It is protocol-agnostic and that provides the ability to use RoboSpice for HTTP/SPDY/FTP/etc. networking.
If you decide to use a more specific technology in conjunction with RoboSpice for handling an HTTP scenario, such as Spring Android, Google Http Java Client, etc. they will provide you, or not, with the headers of the response.
For instance [http://static.springsource.org/spring-android/docs/1.0.x/reference/html/rest-template.html](Spring Android RESTTemplate) does have "entity*" versions of its methods that can give you back the headers. But again, this is not the responsibility of RoboSpice.
When you execute a request using the SpiceManager, you can provide a duration of expiry. This duration indicates whether or not to use any data in the cache, if there are some. It doesn't indicate any expiry duration of the data that the current request will fetch from the network.
Report to question above to get the HTTP headers and use the returned value for data expiration to give an expiry duration to your next request.
Yes, you can, and that should be the best option around. RoboSpice has been designed for networking requests but we acknowledge that it addresses a more general problem : syncing long running background tasks and activities.
To perform such a task using RoboSpice there are 2 steps to follow :
- build you request as usual but don't use any networking in the method
loadDataFromNetwork
- provide your
SpiceService
with a customNetworkStateChecker
that will always declare the network to be available. This way, RoboSpice will always execute your requests (usually, requests are simply discarded if network is not on).
RoboSpice ships with debug logging enabled to help you during development phase.
If you want to turn it off just put this line of code in your SpiceManager
subclass's constructor:
Ln.getConfig().setLoggingLevel(Log.ERROR);
This is not an issue and has been investigated a lot via issue #91.
If you get this exception, it is highly probable that you are either :
- cancelling a request
- stopping the
SpiceManager
from within a request listener's callback method. And you simply can't do this. That's not an RS design problem but more a limitation of java language itself : while iterating through the synchronized set of listeners associated to a request, this set of listeners can't be modified.
A workaround could have been to use an CopyOnWriteArray
but it comes with performance penalty. Moreover, there is no reason to stop the SpiceManager
after a request is complete: RS does it automatically for you, it will shutdown once there are no requests to execute and restart if a new request is executed.
The simple answer is - it doesn't. RoboSpice is working along with Android lifecycle because of using guidelines provided by Google, that means SpiceManager
is started in Activity.onStart()
and stopped it in Activity.onStop()
. SpiceManager
drops requests only when SpiceManager.shouldStop()
is called, and it is called in Activitiy.onStop()
and this call is executed before Fragment.onDetach()
according to the Android lifecycle docs located here: http://developer.android.com/guide/components/fragments.html#Lifecycle. This means RoboSpice in the solution when Activity
controls the SpiceManager
is relying on Activity
lifecycle and Activity
lifecycle determines Fragment
lifecycle in most of the cases as Fragment
is attached to the hosting Activity
. Fragment
doesn't live on it's own. But! Fragment
lifecycle can be different at times when using FragmentTransaction
. This means that RoboSpice may try to deliver a response to a Fragment
that was detached while an Activity
was still operating (i.e. it is not in Paused/Stopped state). This is possible when using transactions and FragmentTransaction.add/replace/remove(...)
for example. To avoid crashes caused by getActivity()
being null
you can check Fragment.isAdded()
method before processing the response and updating Fragment
UI. This solution however drops the response if Fragment
got detached before receiving the response (after 'Fragment.onDetach()' finishes - 'Fragment.isAdded()returns
false`) and you need to make this request again if required.
Other solution is to use second approach which is getting own SpiceManager
in Fragment.onAttach(...)
and releasing the SpiceManager
in Fragment.onDetach()
so you don't have to call for Fragment.isAdded()
and you can attach to the pending request again in Fragment.onAttach()
with SpiceManager.addListenerIfPending(...)
. It will just create another client for the SpiceService
and will fall in nicely with Fragment
lifecycle.