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)
great post .. love it , keep writing post like this :)
Thanks Alot
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?