---
title: "Calling Web Service with Android Architecture Component"
description: "This article is focusing on calling web service with Android Architecture Component."
canonical: https://oozou.com/blog/calling-web-service-with-android-architecture-component-11
locale: en
date: 2017-07-17
author: "OOZOU Team"
---

# Calling Web Service with Android Architecture Component

> This article is focusing on calling web service with Android Architecture Component.

Published: 2017-07-17 · Author: OOZOU Team (Engineering) · 6 min read

# Introduction
**Android Architecture Component** has been one of the topics that really catches my interest (I guess not only me but also, other Android developers). Right now, there are a lot of coding architectures out there such as MVP, MVVM and etc. However, this time Google has provided the official guideline that helps you architect an Android application. Therefore, it really is worth trying it out. In this article, I will focus on calling web service with this architecture.
The source code of this project is on my [Github](https://github.com/BenBoonya/calling-webservice).
Before starting
**_This article will focus on calling web service with_ **_Android Architecture Component._** _The basics of_ **_Kotlin_** _and other libraries such as_ **_Dagger, Retrofit_** _will not be included in this article.
_

# How does the architecture look like?
The picture above is taken from the official Android site. I would like to classify the above picture into two layers.

**Data Layer**

1. **Repository**: Talking to the local data source(database) and remote data source(web service)
2. **Remote data source:** Connecting to web service

**Presentation Layer**

1. **ViewModel:** Communicating to **Repository** then update the data to UI (fragment/activity) respectively
2. **Fragment/Activity:** All about the UI (set up and update)

**Demo Application**

The demo application fetches the data from [https://swapi.co](https://swapi.co/). The application will display a list of species in Star War.

In this article, I will also cover common actions dealing with web service including getting the result, handling error, and showing loading UI. You could clone the code from [here](https://github.com/BenBoonya/calling-webservice) and look at it along with this article.

# Data Layer

**Remote data source**

**Retrofit** is used as a remote data source to connect to web service. The below code is the interface for the API. If you use **Retrofit**, you should already be familiar with this.

**_Source code package_**_: boonya.ben.callingwebservice.api
_

```kotlin
interface Swapi {
    @GET("species/")
    fun getSpecies(): Call<SpeciesList>
}
```

It only includes one endpoint for the sake of simplicity.
**Repository**

The calling to web service happens here, and it also includes receiving data and error from web service. Let’s take a look at the code below.

**_Source code package:_** _boonya.ben.callingwebservice.species_

```kotlin
class SpeciesRepositoryImpl(val apiService: Swapi) : SpeciesRepository {

    override fun getSpecies(successHandler: (List<Species>?) -> Unit, failureHandler: (Throwable?) -> Unit) {
        apiService.getSpecies().enqueue(object : Callback<SpeciesList> {
            override fun onResponse(call: Call<SpeciesList>?, response: Response<SpeciesList>?) {
                response?.body()?.let {
                    successHandler(it.speciesList)
                }
            }

            override fun onFailure(call: Call<SpeciesList>?, t: Throwable?) {
                failureHandler(t)
            }
        })
    }
}
```

As you can see that the function **getSpecies** is **higher-order function**_A higher-order function_** _is a function that takes functions as parameters or returns a function._
The **getSpecies** take two functions as arguments

1. **_(successHandler: (List\<Species\>?) -> Unit )_** This function is called when the call to the web service is successful. It takes **_List\<Species\>_** which is the response data from web service as an argument. You will see later how **ViewModel**can access this data
2. **_(failureHandler: (Throwable?) -> Unit)_** This function is invoked when the call to web service is failing. It also takes **Throwable** as an argument that will be manipulated in **ViewModel.**

By having **Repository,** the presentation layer (Activity/Fragment, ViewModel) will not have to directly access to remote sources. Therefore, if we want to use other remote sources instead of **Retrofit**, we could do without changing the code in the presentation layer.

# Presentation Layer

Before going any further, let me introduce you to another new component called **LiveData.**

Here are some short explanations.

**_LiveData_** _makes normal model class observable._**_MutableLiveData_** _is implementation of_ **_LiveData_**_._ **_MutableLiveData_** _can use a method called_ **_setValue_** _that can be used to assign the new value to the_ **_LiveData.
_**ViewModel**

**ViewModel** is a new component introduced in Android Architecture Component. Instead of putting everything in **Activity/Fragment,** we could separate the code that is not related to UI into **ViewModel.** Moreover, **ViewModel** survive when _configuration changes(rotate screen)_ occur. Normally, **Activity/Fragment** and everything inside will be recreated if there is _configuration change._ However, by using **ViewModel,** the existed one can be reused without creating a new one.

Let’s take a look at an example.
**_Source code package:_** _boonya.ben.callingwebservice.species_

```kotlin
class SpeciesListViewModel : ViewModel() {

    @Inject
    lateinit var repository: SpeciesRepository

    var isLoading = MutableLiveData<Boolean>()

    var apiError = MutableLiveData<Throwable>()

    var speciesResponse = MutableLiveData<List<Species>>()

    fun getSpecies() {
        isLoading.value = true
        repository.getSpecies(
                {
                    speciesResponse.value = it
                    isLoading.value = false
                },

                {
                    apiError.value = it
                    isLoading.value = false
                })
    }
    //ignore other code
}
```

There are three **MutableLiveData** set up to be observed from activity/fragment.

1. **_isLoading:_** set to **true** when start calling web service, and change to **false** when the call is successful or failure.
2. **_apiError_**: if there is an error in calling web service the **Throwable** data will be set to this variable.
3. **_speciesResponse:_** when the data is successfully obtained from web service, the response data will be set to this variable.

**Calling to Repository from ViewModel**

To make **Repository** calls web service, we should trigger the method called **getSpecies.** This method will call another method in the **Repository** which I wrote about in the **Repository** section.

As you can see that **repository.getSpecies(…. , ….)** takes two functions as arguments. The explanations of each argument are down below.

1. The first argument is the function that will be triggered when calling the web service is successful. There will be response data returning from web service can be referred to them as **it**2.  The second argument function is triggered when calling to the web service is fail and the **Throwable** data can be referred to as **it**.

**Activity**

The activity will only contain the code which is related to UI. Here is the code for Activity.

```kotlin
class SpeciesActivity : AppCompatActivity() {

    private val registry = LifecycleRegistry(this)
    private lateinit var viewModel: SpeciesListViewModel
    private lateinit var adapter: SpeciesListAdapter

    override fun getLifecycle(): LifecycleRegistry = registry

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_species)

        //set up ui
        viewModel = createViewModel()
        attachObserver()
        viewModel.getSpecies()
    }

    private fun attachObserver() {
        viewModel.isLoading.observe(this, Observer<Boolean> {
            it?.let { showLoadingDialog(it) }
        })
        viewModel.apiError.observe(this, Observer<Throwable> {
            it?.let { Snackbar.make(rvSpecies, it.localizedMessage, Snackbar.LENGTH_LONG).show() }
        })
        viewModel.speciesResponse.observe(this, Observer<List<Species>> {
            it?.let { adapter.notifyDataSetChanged() }
        })
    }

    private fun createViewModel(): SpeciesListViewModel =
            ViewModelProviders.of(this).get(SpeciesListViewModel::class.java).also {
                ComponentInjector.component.inject(it)
            }

    private fun showLoadingDialog(show: Boolean) {
        if (show) progressBar.visibility = View.VISIBLE else progressBar.visibility = View.GONE
    }
}
```

To make the activity work with Android Architecture Component, the activity should implement **LifecycleRegistryOwner** and also override the method **getLifeCycle()** like above.

Let’s take a close look at **attachObserver()** method. This activity will observe three **MutableLiveData** in **ViewModel.**

1. **_viewModel.isLoading:_** when change occurs to this variable **showLoadingDialog** method will be triggered to show or hide **progressBar**2.  **_viewModel.apiError:_** Snackbar with an error message will show if the change occurs to this variable.
3. **_viewModel.speciesResponse:_** The recycler adapter will be notified when data is set to this value

# Conclusion
I personally like Android Architecture Component a lot. Not only it allows you to write more testable and more maintainable code but also solve the pain that most of Android developer faces like handling configuration change. If you are about to start a new project, it really worth check this architecture out.

**Reference**

\- https://blacklenspub.com/พอกันทีกับ-god-activity-มาวางโครงดีๆ-ด้วย-architecture-components-d89302734ab8

---

Contact OOZOU: hello@oozou.com · +66 2544 0000 · https://oozou.com/contact

More for AI agents: https://oozou.com/llms.txt · every page has a markdown twin at its URL plus ".md"
