Make API Requests in Android using Retrofit
Tags: android, kotlin, restapi, retrofit
Published: 2023-07-26 12:03:59

If you're coming from web development world like me, you definitely had to make api calls or requests and most likely used axios for that (or maybe fetch).
Well... retrofit is just like axios but a little bit more complicated. Let me rephrase, a lot more complicated.
With axios we only needed to do axios.get("end_point_url") to make a simple GET request, in android we need 3 things: a model, an interface, and a retrofit instance.

Model is a class which contains the objects to be obtained from the JSON file. I have to main models:
First is the MovieItem
```Kotlin
data class MovieItem(
    val adult: Boolean,
    val backdrop_path: String,
    val genre_ids: List<Int>,
    val id: Int,
    val original_language: String,
    val original_title: String,
    val overview: String,
    val popularity: Double,
    val poster_path: String,
    val release_date: String,
    val title: String,
    val video: Boolean,
    val vote_average: Double,
    val vote_count: Int
)
```
Second model is for the response of api call
```kotlin
data class MoviesResult(
    val dates: Dates?,
    val results: Movies,
    val page: Int,
    val total_pages: Int,
    val total_results: Int
)
```
Next we need an interface that contains the functions that call the api endpoints.

```kotlin
interface MoviesApi {
    @Headers(
        "Content-Type: application/json",
        "Authorization: Bearer {API_KEY}"
    )
    @GET("popular")
    fun getPopularMovies(): Call<MoviesResult>
}
```
Lastly, the retrofit instance which is an object where we configure retrofit:

```kotlin
object RetrofitClientInstance {
    val moviesApi: MoviesApi by lazy {
        Retrofit.Builder()
            .baseUrl("{BASE_UERL}")
            .addConverterFactory(GsonConverterFactory.create())
            .build()
            .create(MoviesApi::class.java)
    }
}
```
We consume the movies api by calling the retrofit instance like so

```kotlin
class HomeViewModel : ViewModel() {
    private val mutablePopularMovies = MutableLiveData<MoviesResult>()

    init {
        getPopularMovies()
    }

    fun observePopularMovies(): LiveData<MoviesResult> {
        return mutablePopularMovies
    }

    private fun getPopularMovies() {
        RetrofitClientInstance.moviesApi.getPopularMovies()
            .enqueue(object : Callback<MoviesResult?> {
                override fun onResponse(
                    call: Call<MoviesResult?>,
                    response: Response<MoviesResult?>
                ) {
                    mutablePopularMovies.value = response.body()
                }

                override fun onFailure(call: Call<MoviesResult?>, t: Throwable) {
                    Log.d(TAG, "something went wrong ${t.message.toString()}")
                }
            })
    }
}
```
The "observePopularMovies" function is responsible to observe any changes to popular movies data and hand it over to the views.

```kotlin
class MainActivity : AppCompatActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)

        val home = ViewModelProvider(this)[HomeViewModel::class.java]

        home.observePopularMovies().observe(this, Observer {
            if (it != null) {
                // Update your UI with the moviesResult data
                // For example, display the movie titles in a RecyclerView
            } else {
                // Handle error or empty response
            }
        })
    }
}
```