Android Developer

Los Angeles Freelance Developer

Android Developer header image 2

Android Architecture: Structuring Network Calls, Part 3

October 7th, 2012 · 10 Comments · Android, OOP

So far we’ve talked about some theory and OOP design principles and making our request asynchronous. In this post we’re going to discuss what was going on inside of the AsyncTask to make the network request and parse the data. Much like most of my posts, I won’t be discussing how to make a network request or how to parse xml or json. Instead, we’ll keep it broader and continue to talk about the architecture.

Making the call:
Let’s check out FetchRssHeadlinesTask.

27
28
29
30
31
@Override
protected List<RssSnipetVo> doNetworkAction() throws IOException, SAXException {
    command = new ReadRssCommand(rssFeed);
    return command.execute();
}

You can see here that our class delegates the network request to another object. Let’s check out ReadRssCommand.

19
20
21
22
23
24
25
26
27
28
29
public ReadRssCommand(String rssFeed) {
    this.rssFeed = rssFeed;
}
 
public List<RssSnipetVo> execute() throws IOException, SAXException {
    Uri.Builder builder = Uri.parse(rssFeed).buildUpon();
    InputStream inStream = requestStream(builder.toString());
    Document doc = streamToXml(inStream);
    List<RssSnipetVo> items = RssParser.parseItems(doc);
    return items;
}

Skeptic: Wait wait wait! So FetchRssHeadlinesTask delegates to ReadRssCommand which delegates to RssParser? You have 3 classes for 6 actual lines of code? That’s absurd.

Yes that’s correct…well not the absurd part. There’s 2 OOP principles going on here, the Single Responsibility Principle and DRY (Don’t Repeat Yourself). The Single Responsibility Principle states that a class should only do one thing (and do it well. This also means it would only have 1 reason to change.) Let’s look at the responsibilities of each class.

  • FetchRssHeadlinesTask –  makes the request asynchronous. It has the option to perform business logic on the returned results.
  • ReadRssCommand – is used to make the actual http request to the server.
  • RssParser – is used to parse the results returned from the server into Data Objects.

If we look at the responsibilities of the classes it’s clear where to break them up and delegate.  Line numbers are not an indication of this, responsibilities are. Just a general hint: if you have to use the word “and” when describing what your class does, perhaps you should consider if it violates the Single Responsibility Principle.

Let’s consider DRY for a moment now. ReadRssCommand calls some API (notice we don’t even care what url or api it calls. How and what it calls is hidden.) and that returns back an XML result set. Suppose we were to create a SearchRssCommand which took in a search term. The results back from that query would have the same structure as the ReadRssCommand. As such we can reuse the RssParser. If we had put that parsing code in with the network request we’d have to duplicate that same parsing logic in our SearchRssCommand. We would be repeating ourselves. Why is repeating ourselves such a bad idea? Duplicate code is hard to maintain. What happens when I find a bug in the parsing code or perhaps a new node is added to the XML? We’d have to go through all the different places and make change. By having a single point for parsing the XML results, it makes code easier to maintain and it becomes reusable.

I want to point out to make sure it’s clear, it doesn’t matter if we’re using XML or JSON or POST or GET or PUT or whatever. Notice the internals are all encapsulated. It’s all hidden. If we were using JSON instead of XML, I’d still have an RssParser. It would just be parsing JSON instead of XML and the internals of that would still be hidden. If we were using POST instead of GET to fetch the RSS results, it wouldn’t matter. Our structure stays consistent throughout it all.

As a quick summary, AsynTask command is used for business logic. The AsynTask delegates the URL request to another class whose responsibility it is to call the appropriate API with the correct parameters. The results of that API are passed into some type of parser (a custom parser or one that uses reflection or whatever) to translate it into data objects. From there the results are returned to the original requesting client. The specifics of what happens in between aren’t so important.

Sources: Get the sources here!

Tags: ·············

10 responses so far ↓

  • 1 tica // Jun 25, 2013 at 4:56 pm

    First I want to say great job with these articles. You should consider teaching if you’re not already doing that :).

    I have couple of questions regarding your architecture… Where would you construct the url for the service call. Especially if it’s constructed from different variables and possibly some constants. Do you do it in the Command or the NetworkTask subclass, and would you pass all the parameters from activity (controller) or do you retrieve them from within command/task? Also, what if you work with GET, POST, JSON etc. Do you create base command for each like you did with XML and then extend or you create one base class and implement different methods for every type. I’m very interested in your input.

    Thanks again for great articles.

  • 2 musselwhizzle // Jun 25, 2013 at 5:33 pm

    Hi Tica,
    I pass in the variables as needed. I don’t make the task retrieve them. Typically it’s the NetworkTask subclass that pieces together the information needed which let my Commands stay more flexible. As for the building of the url, I tend to build that in the command itself passing in params to that something like

    Uri.Builder builder = Uri.parse(API_ENDPOINT+”newest”).buildUpon();
    builder.appendQueryParameter(“key”, GameTrailers.API_KEY);
    builder.appendQueryParameter(“items”, Integer.toString(pageSize));
    builder.appendQueryParameter(“pageNumber”, Integer.toString(page));

    As for XML vs JSON with the same NetworkTask, well that becomes tricky. Do you make the NetworkTask throw all types of exceptions? I can’t say I’ve had to handle this use-case yet as I generally stick to 1 format per project. If you do some experimenting come back and let us know what you came up with.

    Thanks for the comment and compliment.
    Cheers
    Josh

  • 3 tica // Jun 26, 2013 at 4:53 am

    Hi Josh,

    The reason I’m using more then one format is because I use some 3rd party services which work with XML and our back end works with JSON. Anyway, what I decided to do is handle all the exceptions inside NetworkTask and create different base commands for JSON and XML which will be extended for different services.

    I’ll stick with this for now and check pros and cons at some point. I’ll try to share experience when I do that.

    Thanks for the quick response and keep up the good work.

  • 4 ks // Jul 28, 2013 at 1:01 pm

    Hi Josh,

    Great Job!!! Thanks for sharing!! I have one doubt.. regarding data saving to DB(SQLite)… in doInBackground or in runnable thread in network task onComplete listener of activity

    Thanks
    KS

  • 5 gmtorres // Sep 30, 2013 at 1:59 pm

    Hey Josh,

    Would you handle management of a Bluetooth connection between 2 devices in the same way? I ask because I see many similarities and that is the problem I’m trying to tackle. Bluetooth connection requires an open socket which is tied to an input stream and output stream for passing data. I was originally handling various responsibilities using threads, but after reading your post I’m thinking AsyncTask subclassing is the better option. If not this way, how would you handle BT connections with a SOLID OOP type approach? I’m hoping I can come up with a consistent set of principles with which to handle communication in general, be it network calls, BT actions, NFC communication, etc – all within a MVC OOP approach.

    Thanks much,
    Gerard

  • 6 musselwhizzle // Sep 30, 2013 at 2:52 pm

    Hi Gerard, I unfortunately don’t have enough experience with bluetooth on Android to know how I’d structure it. I’m about to find out though. I’ll try to post back in after a couple days with the approach I take. Cheers! Josh

  • 7 gmtorres // Sep 30, 2013 at 11:56 pm

    Thanks Josh!

  • 8 musselwhizzle // Oct 1, 2013 at 10:30 pm

    I can’t speak for your exact case, but I’m not using AsynTask for any of my Bluetooth LE development. I’m just putting it in a bindable service. This makes more sense to me as Bluetooth LE is 1) async already with it’s callbacks and 2) I need the connection to survive between activities. I’m pretty much just following the docs for this one. Hope that helps.

  • 9 Steve // Aug 10, 2014 at 8:58 pm

    Hi Joshua —

    Thanks for a great tutorial, I’ve really learned a lot. If I can ask a question —

    I really like the way you’ve organized your views as classes, but my UIs are too complex to generate in code. Suppose you wanted the MainView class to be generated from a layout/activity_main.xml with a root RelativeLayout element. How / where would you inflate it, and associate it with the class? Everything I’ve tried seems to break the ListView.

    Thanks again!

  • 10 musselwhizzle // Aug 11, 2014 at 12:51 pm

    How Steve, You could do this: public class MyView extends RelativeLayout. and then in your xml <com.yourapp.something.MyClass> <TextView /> and the just setContentView(R.layout.yourlayout). This approach works if you’re inflating an xml layout. In this approach you can’t call new MyView as there wont be a layout associated with it.

Leave a Comment