Android Developer

Los Angeles Freelance Developer

Android Developer header image 2

Android Architecture: Structuring Network Calls, Part 2

September 30th, 2012 · 8 Comments · Android, OOP

What is the Command Pattern? Even if you don’t know what it is you’ve most likely implemented it before. It’s a pretty simple concept: you encapsulate a behavior that can be executed at a later time. Does that ring a bell? In Android, there are two very common types of command objects that are used: Runnable and AsynTask. Think about it for a moment. In a Runnable, you put all your fancy code in the run method, and then pass that object to a client. Let’s check it out briefly:

1
2
3
4
5
6
runOnUiThread(new Runnable() {
    @Override
    public void run() {
	// do my fancy code here.
    }
});

It’s as simple as that. That’s an implementation of the Command Pattern. AsynTask is the same, but just a slightly more complex implementation as it’s based around The Template Pattern which has hooks that you can implement at different points in the execution. Internally, AsynTask takes care of the logic of when those hooks are called such as onPreExecute() and onPostExecute(), for example. All you do is override those and they are called at the appropriate time.

The Command Pattern is pretty awesome and because of its encapsulation of a single task it’s one of the patterns that gives us the flexibility to apply the Open/Closed Principle we talked about back in Part 1. So without further ado, let’s get out of the theory and start looking at specifics.

Making the Request:
In this section, we’re going to look at how to make the request asynchronous and what to do with the result we get back. If you haven’t done so yet, go ahead and grab the sources here and check out the “business” package. Let’s start by showing how the controller (MainActivity) uses this command.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
fetchTask = new FetchRssHeadlinesTask(url);
fetchTask.setOnCompleteListener(new NetworkTask.OnCompleteListener>() {
    @Override
    public void onComplete(List result) {
	mainView.showProcess(false);
	mainView.bind(result);
    }
});
fetchTask.setOnGenericExceptionListener(new NetworkTask.OnExceptionListener() {
    @Override
    public void onException(Exception exception) {
	mainView.showProcess(false);
	mainView.bind(new ArrayList());
	Toast.makeText(MainActivity.this, "Ooopppsss. Something went horribly wrong!", Toast.LENGTH_LONG).show();
    }
});
mainView.showProcess(true);
fetchTask.execute();

So this looks a little different than your generic AsynTask, but we’ll get to that in a minute. Let’s check out FetchRssHeadlinesTask.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
public class FetchRssHeadlinesTask extends NetworkTask<Void, Void, List<RssSnipetVo>> {
 
	private String rssFeed;
	private ReadRssCommand command;
 
	public FetchRssHeadlinesTask(String rssFeed) {
		this.rssFeed = rssFeed;
	}
 
	@Override
	public void abort() {
		super.abort();
		if (command != null) command.cancel();
	}
 
	@Override
	protected List<RssSnipetVo> doNetworkAction() throws IOException, SAXException {
		command = new ReadRssCommand(rssFeed);
		return command.execute();
	}
 
	@Override
	protected void onPostSuccess(List<RssSnipetVo> result) {
		SampleModel.getInstance().setCurrentRssItems(result);
	}
 
}

So the first thing you may notice is how simple this class is, but in this instance its responsibility is also very simple. This class is responsible for handing the business logic of the returned data. It is not responsible for making the service call or parsing the server’s response. (We’ll cover that later in Part 3) In this instance we simply set the result to the model. But perhaps in your application you may need to do more things like clear out other model properties, sort the data, or any number of things. Separating the responsibilities of using the retrieved response verses getting a response allows us to reuse the network request code in other places without duplicating our logic. Let me repeat that again since it’s pretty important. My concrete classes of AsynTask are used to perform business logic on the returned data (in addition to being asynchronous).

If we look at the name of the class, we can infer what this object does: it fetches the headlines of an RSS feed like the one on this blog, see here. The application we’re exploring is extremely simple, but let’s say we wanted to load the content of a selected RSS item. How might we do that? We could add a class called FetchBlogPostTask. It might look something like this:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
public class FetchBlogPostTask extends NetworkTask<Void, Void, String> {
 
	private String urlToPost;
	private ReadPostCommand command;
 
	public FetchBlogPostTask(String urlToPost) {
		this.urlToPost = urlToPost;
	}
 
	@Override
	public void abort() {
		super.abort();
		if (command != null) command.cancel();
	}
 
	@Override
	protected String doNetworkAction() throws IOException, SAXException {
		command = new ReadRssCommand(urlToPost);
		return command.execute();
	}
 
	@Override
	protected void onPostSuccess(String result) {
		SampleModel.getInstance().setCurrentRssPost(result);
	}
}

The idea here is that for each network request we need to make we have a corresponding Task class that goes along with it. Let’s take this concept back to the Okcupid app from Part 1. Our initial architecture looked something like this:

1
2
3
4
5
6
public class OkcupidApi {
	public void sendMessage(long userId, String message) {}
	public String readMessage(long messageId) {}
	public void blockUser(long userId) {}
	public void unblockUser(long userId) {}
}

But using our Command approach, we have something more like:

  • SendMessageTask
  • ReadMessageTask
  • BlockUserTask
  • UnblockUserTask

You can see the difference here. We encapsulate each of our requests into a command. If we need to add additional APIs we can simply make more commands. We don’t have to open up our original classes and mess with their code to accommodate new features. Our original classes are closed to modification and yet open to extensibility. We’re following the Open/Closed Principle.

That’s seems like a lot of work. I don’t want to have to make a new class each time. Humpft!

Yea, it’s true. Additionally, if you have a lot of APIs you can end up with class explosion meaning you have a ton of classes in the business package. But other than a filing system issue and organization on your computer, in terms of Object Oriented Programming there’s nothing wrong with it. Additionally, you don’t have to do this for every application. Perhaps your application isn’t very network heavy; perhaps the benefits from taking this approach aren’t enough to warrant it in your application. That’s okay! It’s totally your call. You shouldn’t over architect. However, if there is ever a question of which way to do something or if I’m unsure how big the project could get, I favor the approach that will give me the greater flexibility in the project. When something is unknown I favor the more formal approach.

A Nicer AsyncTask:
The above commands were pretty simple to write. We were delegating the internals to another class and only handling the response.  To help facilitate that we subclassed NetworkTask. Let’s talk about the details of NetworkTask. We use this class for anything that needs to go out and fetch data. Much like AsynTask, I added some of my own hook points. I’ll explain the basic idea of the class from the top down. (Side note: feel free skip this section if you don’t care about the specifics of the class. You won’t be missing too much.)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
// NOTE: Wordpress is stripping out my Generics. <Void, ...>. Refer to the zipped code for
// a better example.
abstract public class NetworkTask extends AsyncTask {
 
	public static interface OnCompleteListener {
		public void onComplete(Result result);
	}
 
	public static interface OnSAXExceptionListener {
		public void onSAXException(SAXException exception);
	}
 
	public static interface OnIOExceptionListener {
		public void onIOException(IOException exception);
	}
 
	public static interface OnExceptionListener {
		public void onException(Exception exception);
	}
 
	public static interface OnNetworkUnavailableListener {
		public void onNetworkException(NetworkErrorException exception);
	}
 
	private Exception exception;
	private IOException ioException;
	private SAXException saxException;
 
	private boolean isComplete = false;
	public boolean isComplete() {
		return isComplete;
	}
 
	private boolean isAborted = false;
	public boolean isAborted() { return isAborted; }
 
	private OnCompleteListener completeListener;
	public void setOnCompleteListener(OnCompleteListener completeListener) {
		this.completeListener = completeListener;
	}
 
	private OnExceptionListener exceptionListener;
	public void setOnExceptionListener(OnExceptionListener l) {
		this.exceptionListener = l;
	}
 
	private OnExceptionListener genericExceptionListener;
	/**
	 * This listener gets called if any error happens. It's a convenience method to
	 * catch all the errors in 1 shot.
	 * @param l
	 */
	public void setOnGenericExceptionListener(OnExceptionListener l) {
		this.genericExceptionListener = l;
	}
 
	private OnIOExceptionListener ioExceptionListener;
	public void setOnIOExceptionListener(OnIOExceptionListener l) {
		this.ioExceptionListener = l;
	}
 
	private OnSAXExceptionListener saxExceptionListener;
	public void setOnSAXExceptionListener(SAXException l) {
		this.saxException = l;
	}
 
	private OnNetworkUnavailableListener networkUnavailableListener;
	public void setOnNetworkUnavailableListener(
			OnNetworkUnavailableListener networkUnavailableListener) {
		this.networkUnavailableListener = networkUnavailableListener;
	}
 
	public NetworkTask() {
		super();
	}
 
	/**
	 * Silly AsynTask has the cancel marked as final. Use abort instead;
	 */
	public void abort() {
		isAborted = true;
		cancel(true);
	}
 
	/**
	 * This is where we make the network call. We're not passing object here, so this method must get the params
	 * it needs from the class properties. Since this is thread be sure to make as volatile if needed.
	 *
	 * @return
	 * @throws OmwException
	 * @throws Exception
	 */
	abstract protected Result doNetworkAction() throws IOException, SAXException;
 
	/**
	 * This method runs on the UI Thread.
	 * Use this hook for what happens when the doNetworkAction method returns successfully.
	 *
	 * @param result The result from doNetworkAction
	 */
	 protected void onPostSuccess(Result result) { }
	 protected void onPostFault(Exception e) { }
 
	@Override
	protected void onPreExecute() {
		super.onPreExecute();
		isComplete = false;
		isAborted = false;
		boolean hasNetworkConnection = NetworkUtil.hasInternetAccess(App.getContext());
		if (!hasNetworkConnection) {
			if (networkUnavailableListener != null) {
				networkUnavailableListener.onNetworkException(new NetworkErrorException("Internet connection unavailable"));
			}
			abort();
		}
	}
 
	/**
	 * Mostly likely you should not override this. It's not marked as final, but treat it like that.
	 */
	@Override
	protected Result doInBackground(Params... params) {
		if (isCancelled()) {
			return null;
		}
		try {
			return doNetworkAction();
		} catch (SAXException e) {
			saxException = e;
			return null;
		} catch (IOException e) {
			ioException = e;
			return null;
		} catch (Exception e) {
			exception = e;
			return null;
		}
	}
 
	/**
	 * Out logic to figure what kind of result we got.
	 */
	@Override
	protected void onPostExecute(Result result) {
		super.onPostExecute(result);
		isComplete = true;
		if (isCancelled() || isAborted()) {
			return;
		}
 
		if (saxException != null) {
			onPostFault(saxException);
			if (saxExceptionListener != null) saxExceptionListener.onSAXException(saxException);
			if (genericExceptionListener != null) genericExceptionListener.onException(saxException);
		} else if (ioException != null) {
			onPostFault(ioException);
			if (ioExceptionListener != null) ioExceptionListener.onIOException(ioException);
			if (genericExceptionListener != null) genericExceptionListener.onException(ioException);
		} else if (exception != null) {
			onPostFault(exception);
			if (exceptionListener != null) exceptionListener.onException(exception);
			if (genericExceptionListener != null) genericExceptionListener.onException(exception);
		} 
 
		// SUCCESS!
		else {
			onPostSuccess(result);
			if (completeListener != null) {
				completeListener.onComplete(result);
			}
		}
	}
 
	/**
	 * Convenience method for getting our application model
	 * @return
	 */
	protected SampleModel getModel() {
		return SampleModel.getInstance();
	}
}

From the outside:
From outside the basic AsyntTask there’s no way to know when the action completes and what was the result. With AsynTask you’re forced to subclass it to know this. Additionally, you’d have to override the onPostExecute method and check to see if any errors were thrown. That’s a lot of work. To remedy this, the first block of code above the constructor defines interfaces that allow us to add listeners to the task. If you remember in the controller MainActivity (scroll to the top of this post), the controller set listeners for the onComplete and onError events.

Changing the APIs:
I’m actually not a huge fan of the way AsynTask is designed. While in the later API levels it is getting better I still think some poor decisions were made, but that’s a different story. Anyway, I’ve added a couple methods of my own. The method abort() allows us a way to cancel the Task. Yes, AsynTask does already have a cancel method, but the authors of the class marked it as final which means we can’t override it. If something is canceled in our NetworkTask it only makes sense to abort the http/IO request as well. As such, we use the method abort() instead of directly calling the cancel() method.

You’ll also notice an execute() method I added which takes no parameters. I’m not a fan of passing in an open list of objects. In my humble opinion, there’s no need and it’s messy. What if I want to pass in a long, a string, and a generic data object? I’d have to cast these and rely upon the order. The solution is to pass the params you’ll need in the constructor and then simply execute the command with no parameters. If you’ve ever needed to pass parameters to a Runnable then you’ve already done this.

Our Hooks:
The last couple of methods I’ll talk about are the custom hooks. I’ve added a doNetworkCommand which has the option to throw several errors. This is the method we’ll override to perform our fetching of the data from the server. Notice in our concrete subclasses of NetworkTask we don’t touch onPostExecute. onPostExecute has error checking code and controls the execution path. Based upon the result of the call, either onPostSuccess or onPostFault will be triggered. The subclass should override these methods and then typically update the model.

Up Next:
In Part 3, I’ll be discussing the actual server calls and parsing the response. I promise I’ll eventually write it, but hang tight as this will probably be about a week or more before I can get to it.

Tags: ·········

8 responses so far ↓

  • 1 Jack Le // Nov 19, 2012 at 10:56 am

    Hi Josh, I want to give you a milions thanks for your series about android development. I have learned many things form those articles.
    In this article I have a question, If I have many models in my application, do I have create each NetworkTask for each model like protected

    SampleModel getModel() {
    return SampleModel.getInstance();
    }

    Thank you again for this blog.

    Jack Le

  • 2 musselwhizzle // Nov 19, 2012 at 3:43 pm

    Hi Jack. Glad you enjoyed the articles. Here’s how I think of it and it seems pretty common for software development. “SampleModel” is probably better labeled as “ApplicationModel.” Whatever the name of the project I’m working on is the {Name}Model which acts as the application model, for instance EngadgetModel. The application model generally holds references to other models such as a navigation model or user model or whatever. So it would be something like EngadgetModel.getInstance().getNavigation() or EngadgetModel.getInstance().getUser(). If this is the approach you use, then you only need 1 getModel() method. Additionally, the “getModel()” method I believe is protected (and could have even been final if it’s not). It’s purely for convenience and not a key part of the architecture. Hope that helps some.

    Cheers!
    Josh

  • 3 Jack Le // Nov 19, 2012 at 10:10 pm

    Hi Josh,
    Thank you so much for quick respond. This help me alot. Im thinking about what you said. When I have clearly what I need, I will tell you soon.

    best reragds,
    Jack

  • 4 Android Noob // Dec 29, 2012 at 11:46 am

    Interesting article. Couple questions:

    1) If I chose to use a threadpool and implemented the Tasks as Runnables instead, what would be a good design? The reason I’m asking is that AsyncTasks have OnPreExecute()/
    OnPostExecute(), which allows you to execute code on the thread that the Task was invoked on. If I wanted to do the same thing with Runnables, would it be a good idea to pass in a Handler to post back to the calling thread (i.e. update a view on the UI thread)?

    2) If I have 10-20 webservice calls in my app, I would have 10-20 NetworkTask classes in the project. That’s going to be a lot of exception handling hooks that have to be implemented. Is there a cleaner approach to writing this code using the Command pattern or OO?

  • 5 musselwhizzle // Dec 29, 2012 at 8:44 pm

    @Android Noob, Thanks for taking your time to write.
    1) If you haven’t done so check out the source to AsyncTask. It’s nearly exactly what you are describing: a thread pool with a static handler bound to the UI Looper. To answer your question “…to pass in a Handler to post back…” I would prefer the AsyntTask approach of not having to pass a Handler.

    2) If you have 10-20 webservice endpoints in your app, you would probably have 1 NetworkTask with 10-20 subclasses. The NetworkTask superclass should be doing most of the error handling which would consolidate the error handling to 1 main location while the subclasses would supply the specific api calls and interpreting of that data.

  • 6 Android Noob // Dec 31, 2012 at 10:56 am

    Ok thanks for the reply.

    I’ll take a look at one and see if that’s a better approach.

    Your suggestion for 2) is what I ended up going with for error handling.

  • 7 Stancho // Mar 20, 2013 at 6:18 am

    nice posts, just have a question – why you do not use androidannotations for all this things

  • 8 musselwhizzle // Mar 20, 2013 at 12:52 pm

    The focus of this blog is mainly on architecture and concepts. Using 3rd party libs is up to the reader if he/she chooses too. Cheers.

Leave a Comment


Warning: fsockopen(): php_network_getaddresses: getaddrinfo failed: Name or service not known in /home4/joshm/public_html/wp-content/plugins/sweetcaptcha-revolutionary-free-captcha-service/library/sweetcaptcha.php on line 81

Warning: fsockopen(): unable to connect to www.sweetcaptcha.com:80 (php_network_getaddresses: getaddrinfo failed: Name or service not known) in /home4/joshm/public_html/wp-content/plugins/sweetcaptcha-revolutionary-free-captcha-service/library/sweetcaptcha.php on line 81