Let's set up Retrofit, Gson, and Kotlinx Coroutines to fetch a random quote from ZenQuotes API and display it dynamically in Jetpack Compose.
🔍 1️⃣ Add Dependencies (Retrofit, Gson, Coroutines)
Add these dependencies in your build.gradle.kts
(Module-level):
dependencies {
implementation("com.squareup.retrofit2:retrofit:2.9.0")
implementation("com.squareup.retrofit2:converter-gson:2.9.0") // Convert JSON to Kotlin objects
implementation("org.jetbrains.kotlinx:kotlinx-coroutines-android:1.6.4") // Coroutines
implementation("com.squareup.okhttp3:logging-interceptor:4.9.3") // Debugging HTTP calls
}
🏗 2️⃣ Create the Retrofit API Interface
ZenQuotes API provides random quotes in JSON format. Define the API interface:
import retrofit2.http.GET
import retrofit2.Retrofit
import retrofit2.converter.gson.GsonConverterFactory
import retrofit2.Call
// Step 1: Define Data Model
data class QuoteResponse(val q: String, val a: String) // q = quote, a = author
// Step 2: Define API Interface
interface QuoteApiService {
@GET("api/random") // Endpoint for random quote
fun getRandomQuote(): Call<List<QuoteResponse>> // ZenQuotes returns a List
}
// Step 3: Create Retrofit Instance
object RetrofitInstance {
private const val BASE_URL = "https://zenquotes.io/"
val apiService: QuoteApiService by lazy {
Retrofit.Builder()
.baseUrl(BASE_URL)
.addConverterFactory(GsonConverterFactory.create()) // Convert JSON
.build()
.create(QuoteApiService::class.java)
}
}
🚀 3️⃣ Fetch Quote Using Coroutines
Since Retrofit
's default method (Call
) is synchronous, let's use Coroutines for async operations.
Create a Repository for API Calls:
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.withContext
class QuoteRepository {
suspend fun fetchRandomQuote(): QuoteResponse? {
return withContext(Dispatchers.IO) {
try {
val response = RetrofitInstance.apiService.getRandomQuote().execute()
if (response.isSuccessful) response.body()?.get(0) else null // ZenQuotes returns a List
} catch (e: Exception) {
null // Handle errors
}
}
}
}
🌐 4️⃣ Display Quote in Jetpack Compose
Modify your QuoteScreen
to display fetched quote dynamically.
import androidx.lifecycle.viewModelScope
import androidx.lifecycle.ViewModel
import kotlinx.coroutines.launch
class QuoteViewModel : ViewModel() {
private val repository = QuoteRepository()
var quoteText by mutableStateOf("Tap button for a quote")
var authorText by mutableStateOf("")
fun getNewQuote() {
viewModelScope.launch {
val quote = repository.fetchRandomQuote()
if (quote != null) {
quoteText = "\"${quote.q}\""
authorText = "- ${quote.a}"
}
}
}
}
🎨 5️⃣ Connect ViewModel to Your UI (QuoteScreen
)
Now, update your Composable to use QuoteViewModel
.
@Composable
fun QuoteScreen(viewModel: QuoteViewModel = QuoteViewModel()) {
Column(
modifier = Modifier.fillMaxSize().padding(16.dp),
horizontalAlignment = Alignment.CenterHorizontally,
verticalArrangement = Arrangement.Center
) {
Text(text = viewModel.quoteText, modifier = Modifier.padding(8.dp))
Text(text = viewModel.authorText, modifier = Modifier.padding(8.dp))
Button(onClick = { viewModel.getNewQuote() }) {
Text("Get Quote")
}
}
}
🚀 Final Steps
- Run the app and click the button to fetch a random quote.
- ViewModel ensures state survival across recompositions.
- Coroutines make the API call efficient without blocking UI.
Now you have a fully functional random quote generator integrated into Jetpack Compose! 🚀🔥