I created this easy Android App (written in Kotlin and Jetpack Compose) to assist me to know alternative ways to connect with REST API net service utilizing totally different HTTP Shopper libraries.
I additionally tried to measure the reminiscence and efficiency of utilizing these libraries.
That is the REST API – Meals Classes from TheMealDB the app tries to retrieve. It returns in JSON format.
The app is carried out with MVVM, however the next solely highlights the steps it is advisable do to construct these HTTP shopper libraries.
If you wish to know the small print, please consult with the supply code offered on the finish of this text.
1. Retrofit + Moshi
That is the primary technique I realized whereas creating this Asteroid Rader App in considered one of my Android Kotlin Developer Nanodegree Initiatives.
- Retrofit is the HTTP shopper library to connect with REST API net service
- Moshi is the library to parse JSON response into Kotlin information object
Import Retrofit + Moshi Converter Libraries
def retrofit_version = "2.9.0"
implementation "com.squareup.retrofit2:retrofit:$retrofit_version"
implementation "com.squareup.retrofit2:converter-moshi:$retrofit_version"
def moshi_version = "1.12.0"
implementation "com.squareup.moshi:moshi:$moshi_version"
implementation "com.squareup.moshi:moshi-kotlin:$moshi_version"
Create Knowledge Class for Moshi
information class MoshiMealCategoriesResponse (
val classes: Listing<MoshiMealCategory>
)
information class MoshiMealCategory(
@Json(title="idCategory") val idCategory: String,
val strCategory: String,
val strCategoryDescription: String,
val strCategoryThumb: String
)
@Json
is Moshi annotation and solely is required in case your val title is totally different from the JSON string.
Outline Retrofit + Moshi API Interface
interface RetrofitMoshiMealsApi {
@GET("classes.php")
droop enjoyable getMealCategories(): MoshiMealCategoriesResponse
}
Construct Retrofit + Moshi API
class RetrofitMoshiMealsWebService {
non-public val api: RetrofitMoshiMealsApi by lazy {
createMealsApi()
}
droop enjoyable getMealCategories(): MoshiMealCategoriesResponse {
return api.getMealCategories()
}
non-public enjoyable createMealsApi(): RetrofitMoshiMealsApi {
val moshi = Moshi.Builder()
.add(KotlinJsonAdapterFactory())
.construct()
val retrofit = Retrofit.Builder()
.baseUrl(MainRepository.BASE_URL)
.addConverterFactory(MoshiConverterFactory.create(moshi))
.construct()
return retrofit.create(RetrofitMoshiMealsApi::class.java)
}
}
2. Retrofit + Gson
Much like Moshi, Gson is an open-source Java library to serialize and deserialize JSON to Kotlin information objects.
Since Moshi import has already proven above, I am not going to point out right here once more.
Import Gson Converter Library
implementation "com.squareup.retrofit2:converter-gson:$retrofit_version"
Create Knowledge Class for Gson
information class GsonMealCategoriesResponse (
val classes: Listing<GsonMealCategory>
)
information class GsonMealCategory(
@SerializedName("idCategory") val idCategory: String,
val strCategory: String,
val strCategoryDescription: String,
val strCategoryThumb: String
)
@SerializedName
is Gson annotation, which has similarities to @Json
in Moshi annotation in case your JSON string is totally different from the val title.
Technically I can share the identical information class for all these totally different JSON parser implementation, however I feel it’s cleaner to separate because it requires totally different annotations for various parser libraries.
Outline Retrofit + Gson API Interface
interface RetrofitGsonMealsApi {
@GET("classes.php")
droop enjoyable getMealCategories(): GsonMealCategoriesResponse
}
Construct Retrofit + Gson API
class RetrofitGsonMealsWebService {
non-public val api: RetrofitGsonMealsApi by lazy {
createMealsApi()
}
droop enjoyable getMealCategories(): GsonMealCategoriesResponse {
return api.getMealCategories()
}
non-public enjoyable createMealsApi(): RetrofitGsonMealsApi {
val gsonConverterFactory = GsonConverterFactory.create()
val retrofit = Retrofit.Builder()
.baseUrl(MainRepository.BASE_URL)
.addConverterFactory(gsonConverterFactory)
.construct()
return retrofit.create(RetrofitGsonMealsApi::class.java)
}
}
3. Retrofit + Kotlin Serialization
Much like Moshi and Gson, Kotlin Serialization is an official Kotlin library which can be utilized to serialize and deserialize JSON to Kotlin information objects.
One of many suggestions I obtained within the Android Kotlin Developer NonoDegree is to make use of Kotlin Serialization. The reminiscence and efficiency are higher as a result of it would not use reflection.
Add Kotlin Serialization Plugin
Add this in appbuild.gradle
plugins {
...
import challenge. id 'org.jetbrains.kotlin.plugin.serialization' model "$kotlin_version"
}
Ensure you replace the construct.gradle
on the app degree and never on the challenge degree. If you happen to see this warning beneath, it’s probably you replace the flawed construct.gradle
file (i.e. challenge degree).
Warning:(5, 1) kotlinx.serialization compiler plugin just isn't utilized to the module, so this annotation wouldn't be processed. Just be sure you've setup your buildscript appropriately and re-import challenge.
It took me some time to determine I up to date flawed construct.gradle
. It compiled nice however failed at run time. Do not make the identical mistake I did.
Import Kotlin Serialization Library
implementation "org.jetbrains.kotlinx:kotlinx-serialization-json:1.3.2"
Import Kotlin Serialization Converter + okhttp3 Libraries
There is no such thing as a official Kotlin Serialization Converter for Retrofit from squareup, and we’re utilizing the one from Jake Wharton.
implementation "com.jakewharton.retrofit:retrofit2-kotlinx-serialization-converter:0.8.0"
implementation "com.squareup.okhttp3:okhttp:4.9.3"
okhttp3
is required for "utility/json".toMediaType()
utilization. See Construct Retrofit + Kotlin Serialization part beneath.
Create Knowledge Class for Kotlin Serialization
@Serializable
information class KotlinSerdesMealCategoriesResponse (
val classes: Listing<KotlinSerdesMealCategory>
)
@Serializable
information class KotlinSerdesMealCategory(
@SerialName("idCategory")
val idCategory: String,
val strCategory: String,
val strCategoryDescription: String,
val strCategoryThumb: String
)
Much like @Json
(Moshi) and @SerializedName
(Gson), @SerialName
is used for Kotlin Serialization. Please be aware that it is advisable annotate the category with @Serializable
so as to use the Kotlin Serialization.
Outline Retrofit + Kotlin Serialization API Interface
interface RetrofitKotlinSerdesMealsApi {
@GET("classes.php")
droop enjoyable getMealCategories(): KotlinSerdesMealCategoriesResponse
}
Construct Retrofit + Kotlin Serialization
class RetrofitKotlinSerdesMealsWebService {
non-public val api: RetrofitKotlinSerdesMealsApi by lazy {
createMealsApi()
}
droop enjoyable getMealCategories(): KotlinSerdesMealCategoriesResponse {
return api.getMealCategories()
}
@OptIn(ExperimentalSerializationApi::class)
non-public enjoyable createMealsApi(): RetrofitKotlinSerdesMealsApi {
val contentType = "utility/json".toMediaType()
val retrofit = Retrofit.Builder()
.baseUrl(MainRepository.BASE_URL)
.addConverterFactory(Json.asConverterFactory(contentType))
.construct()
return retrofit.create(RetrofitKotlinSerdesMealsApi::class.java)
}
}
Please be aware that it is advisable add @OptIn(ExperimentalSerializationApi::class)
so as to use the converter library. You additionally want so as to add the opt-in compiler argument in your construct.gradle
module degree file.
android {
...
duties.withType(org.jetbrains.kotlin.gradle.duties.KotlinCompile).configureEach {
kotlinOptions {
freeCompilerArgs += "-Xopt-in=kotlin.RequiresOptIn"
}
}
}
You may as well consult with the next weblog put up:
4. Ktor Shopper + Kotlin Serialization
Ktor shopper is a multiplatform HTTP shopper library.
Import Ktor Shopper with Kotlin Serialization Libraries
def ktor_version = "1.6.8"
implementation "io.ktor:ktor-client-core:$ktor_version"
implementation "io.ktor:ktor-client-cio:$ktor_version"
implementation "io.ktor:ktor-client-serialization:$ktor_version"
Create Ktor Shopper and Implement API Interface
The info class is strictly the identical with the Kotlin Serialization information class above . So I am not going to point out right here once more.
To make use of Ktor Shopper, we do not really want to outline the interface as required by Moshi. You may simply name ktorHttpClient.get("URL right here")
API instantly.
class KtorKotlinSerdesMealsWebService {
non-public val ktorHttpClient = HttpClient {
set up(JsonFeature) {
serializer = KotlinxSerializer()
}
}
droop enjoyable getMealCategories(): KotlinSerdesMealCategoriesResponse {
return ktorHttpClient.get("${MainRepository.BASE_URL}classes.php")
}
}
Reminiscence and Efficiency
I added this Allow Efficiency Take a look at
examine field to the principle display screen. When it’s checked, it’ll name the API 10 occasions for efficiency testing.
I ran some reminiscence and efficiency checks and listed below are the outcomes. I ran a few occasions and took the typical. I additionally restarted the app to run HTTLP shopper library independently, so the outcomes will not be overlapped.
HTTP Shopper Library | Reminiscence Utilization | Efficiency |
Retrofit + Moshi | 22 M bytes | 4.8 seconds |
Retrofit + Gson | 19 M bytes | 4.9 seconds |
Retrofit + Kotlin Serialization | 20 M bytes | 4.9 seconds |
Ktor Shopper + Kotlin Serialization | 22 M bytes | 10.8 seconds |
Reminiscence and efficiency for Retrofit + Gson and Retrofit + Kotlin Serialization are related. Retofit + Moshi makes use of barely extra reminiscence with related efficiency, nevertheless it might be simply false constructive.
However, what occur to Ktor Cilent? Ktor Shopper’s efficiency is round 2x slower!
Conclusion
Earlier than I ran the reminiscence and efficiency, I had an impression Ktor Shopper + Kotlin Serialization should be the most suitable choice, nevertheless it turned out to be worst! Perhaps it’s due to multiplatform overhead?
Additionally, the declare for Kotlin Serialization use much less reminiscence and quicker might be not true. It’s about the identical as Moshi and Gson or I didn’t run the check proper?
It is vitally apparent the selection is Retrofit.
Personally, I’ll most likely select
- Moshi over Gson as a result of Moshi is a more moderen library than Gson
- Moshi over Kotlin Serialization as a result of Retrofit Kotlin Serialization Converter is NOT an official library(not a part of the squareup libraries).
Given this little analysis that I’ve executed, my go-to is Retrofit + Moshi.
Supply Code
GitHub Repository: Demo_SimpleRestAPI