9

In the current app that I am developing with a co-worker, we're using IntentServices with Volley calls inside to process RESTful API network requests. It's just simple JSON string data, and some small images.

My question to those experienced in processing network requests is this: is there something more appropriate, or cleaner to implement out there?

From what I understand, the advantage of using an IntentService is that it runs in the background off the main thread, and is typically one of the last things killed by the Android OS. The downside being that IntentServices are run sequentially.

I've been reading a lot about RxJava, and Retrofit, and feel like our needs could be better served with that combination. Retrofit may be enough on its own, but I'd really appreciate some third-party insight.

Willi Mentzel
  • 27,862
  • 20
  • 113
  • 121
Ryan Simon
  • 345
  • 2
  • 13
  • You may want to explore Android Volley Library : https://developer.android.com/training/volley/index.html – AADProgramming Jul 10 '15 at 17:30
  • @AADTechnical Here's the interesting part, we're using Volley inside our IntentServices. – Ryan Simon Jul 10 '15 at 17:34
  • I would definetly recommend Rxjava and retrofit – rahul.ramanujam Jul 10 '15 at 17:40
  • @r7v anything in particular about that combo that you believe is more advantageous? – Ryan Simon Jul 10 '15 at 17:46
  • @RyanSimon why not just use a normal Service? As for RXJava, it is a bit tricky to get a hang of, but it is worth the time investment because it provides for an incredible amount of flexibility. Definitely use Retrofit to make your network requests and to serialize/deserialize any responses. Retrofit has a quasi-"wrapper" for Gson which makes serialization of JSON objects returned from your network requests very easy. – Virat Singh Jul 10 '15 at 17:48
  • I consider Retrofit with GSON everytime I start an app with networking. Retrofit has inbuilt support for GSON. Rxjava makes handling concurrency easier. Retrofit alsosupports rxjava , you can get the response as objects or observable (rxjava). One thing I would like to point is Rxjava has a steep learning curve , you would have to consider it if you are planning to start with Rxjava – rahul.ramanujam Jul 10 '15 at 17:51
  • @r7v Thanks for the feedback, I appreciate it. Sounds like Retrofit and RxJava are the way to go. – Ryan Simon Jul 10 '15 at 18:17
  • Saying "network requests" is nearly useless. The patterns for network I/O depend greatly upon the nature of what that network I/O is. What you do for implementing a VOIP client is different than what you might do for an email client, for example. A `Service` (whether `IntentService` or otherwise) solves specific problems that are orthogonal to the problems solved by Retrofit, which solves specific problems that are orthogonal to the problems solved by RxJava. – CommonsWare Jul 10 '15 at 18:53
  • @CommonsWare That's a great point. I should have been more specific. We're doing RESTful API calls (simple JSON string data), and we're sometimes downloading/uploading small images to our server. – Ryan Simon Jul 10 '15 at 20:23

3 Answers3

22

My general rule of thumb is:

  • If the network I/O should be under a second, and you don't mind if it does not run to completion, any asynchronous option should be fine.

  • If the network I/O should be more than a second, or you really want to increase the odds that it will run to completion, use a Service. Whether you use IntentService or some other Service implementation is up to you, but you want to have a Service as an indicator to the OS that you're doing work, so it doesn't terminate your process quite so quickly once your app moves to the background. Remember that "moves to the background" is not always something initiated directly by the user, as incoming phone calls and such also move you to the background.

  • If the network I/O will take more than 15 seconds, not only do you need to use a Service, but you need to think about a WakeLock (via my WakefulIntentService, or WakefulBroadcastReceiver, or your own carefully-managed WakeLock) and possibly a WifiLock. 15 seconds is the minimum auto-screen-off period in Settings, which is where that figure comes from.

With all that in mind:

The downside being that IntentServices are run sequentially.

I am translating this as "an IntentService has a single thread for processing requests". This is true. In cases where you need a Service and you need parallel processing, create your own Service. Just be sure to call stopSelf() when you have no outstanding work.

I've been reading a lot about RxJava, and Retrofit, and feel like our needs could be better served with that combination

This has nothing to do with whether or not you use a Service. Just don't try doing asynchronous stuff (e.g., a Retrofit call using a Callback) from an IntentService, as you defeat the purpose of the IntentService (indicating to the OS that you're doing work). So, from an IntentService, you would use Retrofit's synchronous API, sans a Callback.

CommonsWare
  • 986,068
  • 189
  • 2,389
  • 2,491
  • This is a great explanation, thank you. Just to make sure I understand the use case: I would want to use a Service when syncing network results with my database (since I really want that to complete correctly), but if I'm simply requesting some JSON containing blog post text (or any data small enough to quickly fetch again), it's not important enough to go through the trouble of setting up a Service for that. Does that make sense? – Ryan Simon Jul 10 '15 at 20:51
  • 1
    @RyanSimon: That seems reasonable. My typical analogy is a Twitter client. You really don't need a service for downloading avatars. You might use a service for downloading timelines, but that would be mostly if you were keeping them sync'd offline, and you were updating the local database periodically (`AlarmManager`, `SyncManager`, etc.). Even posting a tweet you might skip the service. But setting up a new Twitter account, or any operations that might deal with attachments (e.g., uploading a picture as part of a tweet) should use a service. – CommonsWare Jul 10 '15 at 21:21
0

Using IntentServices just to perform a simple network request, IMO, is to much. You should use an AsyncTask if you don't want to use a library or if you prefer to go for Retrofit, Volley... (I would recommend Retrofit). IMO, Services, or in this case IntentService are designed to execute long background tasks.

Sandro Machado
  • 9,921
  • 4
  • 36
  • 57
  • What makes you say that an IntentService is too much for a network request? What about it is bad practice? – Ryan Simon Jul 10 '15 at 17:46
  • "Using IntentServices just to perform a network request is to much" -- that would depend entirely on what the network request is. Downloading a large file is different than downloading a Twitter avatar, for example. – CommonsWare Jul 10 '15 at 18:50
  • True @CommonsWare, I will update the Answer. IMO, I only use an IntentService when I need to perform a set of requests, or perform a request and persist data... To perform a single request I prefer to use something more simple to integrate, like Retrofit or other tools. – Sandro Machado Jul 10 '15 at 18:58
0

The real question is: do you load data to populate an Activity in the foreground or for doing background work, even when no UI is visible?

For background work, a Service is the way to go. You don't even need an IntentService if you rely on the threading management of Volley.

For foreground work, consider using Loaders, or Volley or Rxjava calls directly inside your Activity/Fragment.

BladeCoder
  • 12,779
  • 3
  • 59
  • 51