DEV Community

Cover image for The beauty of Retrofit 2.6.0 with Coroutines support
Nwokocha wisdom maduabuchi
Nwokocha wisdom maduabuchi

Posted on

The beauty of Retrofit 2.6.0 with Coroutines support

Alt Text
Hello Dev,
I will be teaching you how to build a simple project using Retrofit 2.6.0 with its inbuilt support for Coroutines, this will help you to achieve better performance and reduces boilerplate codes significantly. 😍😍😍😍🥰🔥🔥

Note:

This tutorial assumes that you are familiar with the basics of the Retrofit library. If you are completely new to Retrofit, I advise you to read through http://www.kotlincodes.com/kotlin/retrofit-with-kotlin/ first.

New:

Retrofit 2.6. 0 has been released with support for suspend functions. This allows you to express the asynchrony of HTTP requests in an idiomatic fashion for the Kotlin language.

@GET("users/{id}")
suspend fun user(@Path("id") id: Long): User

Behind the scenes this behaves as if defined as fun user(...): Call and then invoked with Call.enqueue. You can also return Response for access to the response metadata.
follow up threads on the Retrofit release: https://github.com/square/retrofit/blob/master/CHANGELOG.md

What is the purpose of this article
1: learn how to build clean, readable and maintainable code
2: learn how to work with retrofit 2.6.0
3: learn how to work with MVVM architecture
4: learn how to work with a repository pattern

In this article I will be using an app I built for learning purposes called " Wammy ", the application is written in Kotlin and it uses MVVM, implemented repository, view model, live data and real-time internet connectivity check.

Alright lets 👀👀👀

First steps we are to add the necessary Dependencies

Build.gradle(module: app)


dependencies {
    def lifecycle_version = "2.3.0-alpha01"
    def arch_version = "2.1.0"
    def activity_version = "1.2.0-alpha02"

    implementation 'com.squareup.retrofit2:converter-gson:2.6.0'
    implementation 'com.squareup.retrofit2:retrofit:2.6.0'
    kapt "androidx.lifecycle:lifecycle-compiler:$lifecycle_version"
    implementation 'com.github.wise4rmgod:AdnetwrokManager:0.1.0'
    // Kotlin
    implementation "androidx.activity:activity-ktx:$activity_version"
    // Lifecycles only (without ViewModel or LiveData)
    implementation "androidx.lifecycle:lifecycle-runtime-ktx:$lifecycle_version"
    // ViewModel
    implementation 'androidx.lifecycle:lifecycle-viewmodel-ktx:2.3.0-alpha01'
    // LiveData
    implementation "androidx.lifecycle:lifecycle-livedata-ktx:$lifecycle_version"
    // Coroutines
    implementation "org.jetbrains.kotlinx:kotlinx-coroutines-android:1.3.2"

}



The second step is to know the API Endpoint to work with, in this example we will work :

GET https://jsonplaceholder.typicode.com/posts

the Endpoint will return

[
  {
    "userId": 1,
    "id": 1,
    "title": "sunt aut facere repellat provident occaecati excepturi optio reprehenderit",
    "body": "quia et suscipit\nsuscipit recusandae consequuntur expedita et cum\nreprehenderit molestiae ut ut quas totam\nnostrum rerum est autem sunt rem eveniet architecto"
  }
]

The third step is to create a Retrofit interface. in this example, it will be


interface Webservice {
    @GET("/posts")
    suspend fun getTodo(): Todou
}

After that let's implement the Retrofit builder that will return our webservice:

class RetrofitClient {
    companion object {
        val retrofit = Retrofit.Builder()
            .baseUrl(Constant.BASE_URL)
            .addConverterFactory(GsonConverterFactory.create(GsonBuilder().create()))
            .build().create(Webservice::class.java)
    }
}

The next step is to create the Repository class which creates the instance of the retrofit service and initiates the API call, our method for this call should be a suspend function as it will later be called through a coroutine.

class TodoRepository {

    var client: Webservice = RetrofitClient.retrofit

    suspend fun getTodo() = client.getTodo()
}


Now that our repository is set up we can create a method in the ViewModel which uses the liveData builder to create a process on the IO thread.

class TodoViewmodel : ViewModel() {
    val repository: TodoRepository = TodoRepository()

    val firstTodo: LiveData<Todou> = liveData(Dispatchers.IO) {
        val retrivedTodo = repository.getTodo()
        emit(retrivedTodo)
    }

}

The emit function emits the changes in the underlying database to the observer variables, in our case which will be located in the MainActivity.

val viewModel: TodoViewmodel by viewModels()
    private lateinit var binding: ActivityMainBinding
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        binding = ActivityMainBinding.inflate(layoutInflater)
        setContentView(binding.root)

        gotonextativity()
        checknetworkstatus()

    }

    private fun checknetworkstatus() {
        CheckNetworkStatus.getNetworkLiveData(applicationContext).observe(this, Observer { t ->
            when (t) {
                true -> {
                    showdummy()
                }
                false -> {
                    Toast.makeText(this, "No Network Connection", Toast.LENGTH_SHORT).show()
                }
                null -> {
                    // TODO: Handle the connection...
                }
            }
        })
    }

    private fun showdummy() {
        viewModel.firstTodo.observe(this, Observer { t ->
            binding.recyclerView.adapter =
                DummyAdapter(t, applicationContext)
            binding.recyclerView.adapter?.notifyDataSetChanged()
        })
    }

    }
}


we can see the observer observing the value of t from the API and updating the UI accordingly.

Hurray!!! your code is cleaner, readable and leverages the coroutine support.
Thanks for your time 🥰🔥🔥
follow me on Twitter: https://twitter.com/Joklinztech
full project Github: https://github.com/wise4rmgod/Wammy

Top comments (3)

Collapse
 
nameisjayant profile image
Jayant Kumar

great post .. love it , keep writing post like this :)

Collapse
 
wise4rmgod profile image
Nwokocha wisdom maduabuchi

Thanks Alot

Collapse
 
artemkw profile image
ArtemKw

Thank you for the informative post! I tried to change the model (data class) a little, and when compiling I got the error: "cannot find symbol
private com.example.wammy.model.News dataList; ^ symbol: class News
location: package com.example.wammy.model"
What can it be?