Member preview

The Evolution of Android Network Access

Android has been in the industry for more than 10 years, and how developer use Android to access the Network has also evolved. Here I’m sharing my view of this evolution with an app with code example given. Enjoy the journey!

Network Access Example App (github code link below)

Dinosaur Age — Direct Access

In the beginning, network access is treated just like any code. You could code into your Android Activity as you like, using it directly in the main thread (aka UI thread).

String result = Network.fetchHttp(searchText);
view.updateScreen(result);

Before Android 2.2, code as above is perfectly fine to make an Android App.

However, this is not ideal as network access code is slow (up to several seconds, which is like a lifetime for a response time in an App!), and will halt the app to feel irresponsive.

To ensure App behave well, Android now will throw NetworkOnMainThreadException during run time when it detects such operation.

There’s a workaround to still force Android to permit such operation on main thread (as coded in my example app), but it is not something anyone should do (except for education purposes like this one).

Stone Age — Using Thread

Experienced programmer know that for more responsive Apps, they could move the network access task to a background thread. This allow the UI to be still responsive while the network fetching work is still in progress.

The code example as below.

thread = new Thread(new Runnable() {
@Override
public void run() {
final String result = Network.fetchHttp(searchText);

// Run the result on Main UI Thread
new Handler(Looper.getMainLooper()).post(new Runnable() {
@Override
public void run() {
view.updateScreen(result);
}
});
}
});

thread.start();

The above code is the simple form of network fetching in thread. Do note to update the screen, it has to be handled later in the UI thread i.e. Looper.getMainLooper(). If not, you’ll see CalledFromWrongThreadException get thrown.

There’s various deficiencies on this approach, as managing thread is always tricky, as well as cancelling it. Passing such challenging job to developer risk the quality of the App, so Google has to do something about it.

Bronze Age — AsyncTask

With the disabling of running network access code on main thread, Google now provides a recommended approach of network access. It is called AsyncTask.

It has various cool feature, such as allowing pre-fetch and post-fetch operation on the main thread and then the network access could be done on the background thread. It also allow progressive update, which looks cool.

Code sample as below

private static class MyAsyncTask extends AsyncTask<String, Void, String> {

private WeakReference<MainView> view;

// only retain a weak reference to the activity
MyAsyncTask(MainView view) {
this.view = new WeakReference<>(view);
}

@Override
protected String doInBackground(String... params) {
String result = Network.fetchHttp(params[0]);
return result;
}

@Override
protected void onPostExecute(String result) {
if (view.get() != null) {
view.get().updateScreen(result);
}
}
}

At some point this was called the STANDARD way of network access code. Various tutorial could be found related to it on the internet.

Even though this is introduced by Google, various flaws has been identified by developers especially in regards to how it could correspond to Android life cycle. Below is one article shared.

Hence though it was the STANDARD, not many people are using it anymore.

Middle Age — Intent Service

Due to the dissatisfaction with AsyncTask, another popular approach emerge. That is using IntentService of Android.

This is not a newly introduce approach by Google to overcome deficiency of AsyncTask. It was originally created as an approach for a long lasting background services (e.g. for downloading a file etc).

However given that AsyncTask was so badly viewed by the community, developer start considering this approach as the alternative.

This approach is not easily elaborate with some snippet of code, but in a diagram as below. The IntentService resides outside the Activity, so it has to be registered separately in AndroidManifest.

The IntentService is treated like another thread, and perform the network access as below.

@Override
protected void onHandleIntent(@Nullable Intent intent) {
String searchText = intent.getStringExtra(PARAM_IN_MSG);
String result = Network.fetchHttp(searchText);

Intent broadcastIntent = new Intent();
broadcastIntent.setAction(ACTION_RESP);
broadcastIntent.addCategory(Intent.CATEGORY_DEFAULT);
broadcastIntent.putExtra(PARAM_OUT_MSG, result);
sendBroadcast(broadcastIntent);
}

Once it is done, it broadcast the result over to the BroadcastListener, that pass the result back to Activity.

Well, as hinted above, though this seems like an alternative, but a relatively heavy-weighted approach. It is just too much if one just needed a simple network access.

Industrial Age — RxJava

With the advent of Functional Programming popularity, and reactive programming, RxJava is being introduced to the Android community.

Very quickly, the STANDARD way of network access is the RxJava way of doing thing.

disposable = Single.fromCallable(new Callable<String>() {
@Override
public String call() throws Exception {
return Network.fetchHttp(searchText);
}
})
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(new Consumer<String>() {
@Override
public void accept(String s) throws Exception {
view.updateScreen(s);
}
});

This very style of coding gain it’s popularity due its ability to defined main thread and background thread in a chaining approach as above.

I think if someone claim to say he has used RxJava, there’s a likelihood he has used it only in the network access side of code, and not the other part of actual reactive style of coding.

This phenomena is because Reactive Programming itself its a relative tricky concept to grasp, and adds on to the need of using Anonymous Classes (due to Android development at that time is limited to Java 6 and 7), makes it not a fun thing to code.

Current Time — Rxjava in Kotlin

In 2017, Google announced the first class citizen Kotlin support in Android Studio. The wild fire spread that Kotlin usage in Android now grow like crazy… With the availability of lambda in replacing Anonymous Classes, The use of RxJava becomes much more cleaner.

Checkout the equivalent code of RxJava network access provided previously in Kotlin below

disposable = Single.fromCallable { Network.fetchHttp(searchText) }
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe { result -> view.updateScreen(result) }

The code is more concise while achieving the same goal. Hence RxJava approach of network access gained further popularity. More and more interesting RxJava approaches are explored to expand it use in more elegant network fetching way.

Below are two articles related to that

Future — Coroutines

Well, even though RxJava is doing a great job now for many, it’s learning curve it still steep for many beginner. The reactive approach of programming is not natural to many. The link between the source (network fetched result) linking to it’s destiny (result sent to UI View) is deems not directly connected.

On the latest development of Kotlin, Coroutines is now introduced. It is though in experimental stage, it looks relatively promising.

The main gist of it is, it makes asynchronous code looks so much like synchronous as below, through it’s ability to suspend function.

job = launch {
val result = Network.fetchHttp(searchText)

launch(UI) {
view.updateScreen(result)
}
}

If one prefers a more elegant way, with concept like future or promises that looks more reactive in nature, it could also do so with it’s async-await style of coding.

val defer = async {
Network.fetchHttp(searchText)
}

job = launch(UI) {
view.updateScreen(defer.await())
}

Hence I view coroutines is now bridging the new learning community as well as the experienced gurus.

There’s a very nice article that combine Kotlin’s coroutines with the Android Lifecycle API.

Just love code that looks like this (extract from the article link below)

load { restApi.fetchData(query) } then { adapter.display(it) }

Very promising I think. That’s my prediction of what’s next in term of Network Access trend for Android in the coming months… But I’m open to other views.


Thanks for reading this far. Hopes you enjoy the journey of how Android Network Access has evolve. As promised, you could get the code from the github below.

I hope you appreciate this post and it’s helpful for you. Do share with others.

You could check out my other interesting topics here.

Follow me on medium, Twitter or Facebook for little tips and learning on Android, Kotlin etc related topics. ~Elye~