Are you looking for an up-to-date example of integrating Dagger Hilt with Retrofit in 2023? Look no further! In this tutorial, we will explore the seamless combination of Dagger Hilt, a powerful dependency injection framework, with Retrofit, a popular networking library. We will guide you through the process of setting up Dagger Hilt and Retrofit in your Android application, providing you with a comprehensive example that leverages the latest features and best practices. By the end of this tutorial, you'll have a solid understanding of how to use Dagger Hilt with Retrofit to efficiently handle dependency injection and network requests in your Android projects. Let's dive in and unlock the potential of these powerful tools together!
1. Install Dependencies for Dagger hilt with retrofit example 2023
//retrofit
implementation 'com.squareup.retrofit2:retrofit:2.9.0'
//Jsoup (For Parsing Html Doc)
implementation 'org.jsoup:jsoup:1.16.1'
//Scalars
implementation 'com.squareup.retrofit2:converter-scalars:2.9.0'
//dagger hilt (Replace $daggerHilt with latest version available)
implementation("com.google.dagger:hilt-android:$daggerHilt")
kapt("com.google.dagger:hilt-android-compiler:$daggerHilt")
implementation("androidx.hilt:hilt-navigation-compose:1.1.0-alpha01")
//coroutines ((Replace $coroutine with latest version available)
implementation("org.jetbrains.kotlinx:kotlinx-coroutines-android:$coroutine")
implementation("org.jetbrains.kotlinx:kotlinx-coroutines-core:$coroutine")
Also, Add these followings in Plugins
id "kotlin-kapt"
id "com.google.dagger.hilt.android"
2. Create a API Interface
import retrofit2.Response
import retrofit2.http.GET
import retrofit2.http.Query
interface ApiService {
@GET("joSrchRsltList/")
suspend fun searchJobs(
@Query("emc") emc: String,
@Query("sac") sac: String,
@Query("jc") jc: String
): Response<String>
}
Explanation : The ApiService interface defines the API endpoints for network requests.
It contains a single method searchJobs annotated with @GET and specifying the endpoint path.
Query parameters emc, sac, and jc are provided using the @Query annotation.
The method returns a Response<String> object wrapped in a suspend function, indicating it can be executed asynchronously.
3. Create MyApplication Class
import android.app.Application
import dagger.hilt.android.HiltAndroidApp
@HiltAndroidApp
class MyApplication:Application() {
}
Important Step: Go to Manifest File, Give Internet Permission and add android name in application section. In my case my class name is "MyApplication". It might differ in your case.
<application
android:name=".MyApplication"
</application>
Explanation :
This code defines the MyApplication class, which is used to initialize Hilt in the application.
The @HiltAndroidApp annotation is added to the MyApplication class, indicating that it should be the entry point for Hilt-generated code.
4. Create a Object Module to define all DI functions
import dagger.Module
import dagger.Provides
import dagger.hilt.InstallIn
import dagger.hilt.components.SingletonComponent
import okhttp3.OkHttpClient
import retrofit2.Retrofit
import retrofit2.converter.scalars.ScalarsConverterFactory
import javax.inject.Singleton
@Module
@InstallIn(SingletonComponent::class)
object NetworkModule {
@Provides
@Singleton
fun provideOkHttpClient(): OkHttpClient {
return OkHttpClient.Builder()
.build()
}
@Provides
@Singleton
fun provideRetrofit(okHttpClient: OkHttpClient): Retrofit {
return Retrofit.Builder()
.client(okHttpClient)
.baseUrl("https://townwork.net/")
.addConverterFactory(ScalarsConverterFactory.create())
.build()
}
@Provides
@Singleton
fun provideApiService(retrofit: Retrofit): ApiService {
return retrofit.create(ApiService::class.java)
}
}
Explanation:
The code defines the NetworkModule module responsible for providing dependencies related to networking.
The @InstallIn(SingletonComponent::class) annotation specifies that the module should be installed in the SingletonComponent, which is the application-level component.
The provideOkHttpClient function provides an instance of OkHttpClient using the OkHttpClient.Builder.
The provideRetrofit function provides an instance of Retrofit with a base URL and converters for scalars (String response) using ScalarsConverterFactory.
The provideApiService function provides an instance of ApiService using the Retrofit instance.
Step 5: Create class WebScraper
import android.util.Log
import com.example.baitosearchtry2.network.ApiService
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch
import org.jsoup.Jsoup
import javax.inject.Inject
class WebScraper @Inject constructor(private val apiService: ApiService) {
fun scrapeData() {
Log.d("My-Tag", "Content Called")
CoroutineScope(Dispatchers.IO).launch {
try {
// Make the API call using the ApiService
val response = apiService.searchJobs("07", "37103", "021")
if (response.isSuccessful && response.body() != null) {
// Handle the successful response
val responseBody = response.body()
responseBody?.let {
// Parse HTML content using Jsoup
val doc = Jsoup.parse(it)
val htmlContent = doc.html()
// Process the HTML content as per your requirements
Log.d("My-Tag", htmlContent)
}
} else {
// Handle the unsuccessful response
Log.e("WebScraper", "API request failed with code: ${response.code()}")
}
} catch (e: Exception) {
// Handle any exceptions that occur
Log.e("WebScraper", "Error: ${e.message}", e)
}
}
}
}
Explanation:
The WebScraper class is responsible for scraping website data using the provided ApiService.
The apiService dependency is injected through the constructor using @Inject.
The scrapeData function is defined to initiate the scraping process.
Inside the CoroutineScope, an API call is made using the apiService to retrieve data.
The response is checked for success and non-null body.
If the response is successful, the HTML content is parsed using the Jsoup library and logged.
If the response is unsuccessful, an error message is logged.
Exceptions are caught and logged in the catch block.
Step 6: Call It in Main Activity
@AndroidEntryPoint
class MainActivity : ComponentActivity() {
@Inject
lateinit var webScraper: WebScraper
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContent {
MainNavigation()
}
scrapeWebsiteData()
}
private fun scrapeWebsiteData() {
lifecycleScope.launch {
val response = webScraper.scrapeData()
Log.d("answer", response.toString())
}
}
}
Explanation:
The code snippet defines the MainActivity class, which is the entry point of the application.
The @AndroidEntryPoint annotation is provided by Dagger Hilt and marks the activity as injectable.
The webScraper variable is annotated with @Inject, indicating that it should be provided by Dagger Hilt.
In the onCreate method, the content view is set using setContent to the MainNavigation composable.
The scrapeWebsiteData method is called to initiate website data scraping.
Inside the scrapeWebsiteData method, a coroutine is launched using lifecycleScope.launch to perform the scraping asynchronously.
The response from the web scraper is logged using Log.d.
That is it, Now run the App and see you will have the HTML doc in your Log. If you have doubts , Let me know in the comment section. I will see you in the next one.
Comments