Dagger 2 Android Example using Retrofit - GeeksforGeeks

21 Dec, 2020
Dagger 2 Android implementation is easier and it is based on Dependency Injection Architecture. Dependency Injection is a design pattern, which is a concept of Object-Oriented Programming, where we don’t create an object of another class inside a class using the new keyword (for Java). Instead, we supply the needed object from the outside. It is a fully static, compile-time dependency injection framework for both Java and Android. It is an adaptation of an earlier version created by Square and now maintained by Google. Note that we are going to implement this project using the Java language. 
Dependency Provider: Dependencies are the objects that we need to instantiate inside a class. We cannot instantiate a class inside a class. The person who will provide us the objects that are called dependencies is called Dependency Provider. dagger2 is the class that you want to make a Dependency Provider, It needs to annotate it with the @Module annotation.
Dependency Consumer: Dependency consumer is a class where we need to instantiate the objects. Dagger will provide the dependency, and for this, we just need to annotate the object declaration with @Inject.
Component: The connection between our dependency provider and dependency consumer is provided via an interface by annotating it with @Component. And the rest of the thing will be done by Dagger.
Step 1: Create a New Project
To create a new project in Android Studio please refer to How to Create/Start a New Project in Android Studio. Note that select Java as the programming language.
Step 2: Before going to the coding section first you have to do some pre-task
Before going to the coding section first you have to do some pre-task. Go to the app > res > values > colors.xml section and set the colors for your app.
XML
<?xml version="1.0" encoding="utf-8"?><resources>    <color name="colorPrimary">#0F9D58</color>    <color name="colorPrimaryDark">#0F9D58</color>    <color name="colorAccent">#FF4081</color></resources>
Go to the Gradle Scripts > build.gradle (Module: app) section and import the following dependencies and click the “Sync Now” on the above pop up.
// these two lines are added for retrofit
implementation ‘com.squareup.retrofit2:retrofit:2.7.2’
implementation ‘com.squareup.retrofit2:converter-gson:2.7.2’
// these two lines are added for dagger
implementation ‘com.google.dagger:dagger:2.13’
annotationProcessor ‘com.google.dagger:dagger-compiler:2.13’
Go to the app > manifests > AndroidManifests.xml section and allow “Internet Permission“. Below is the code for the AndroidManifests.xml file.
<!– the internet permission , then only api calls can be retrieved –>
<uses-permission android:name=”android.permission.INTERNET” />
Step 3: Designing the UI
Below is the code for the activity_main.xml file. This will be under the app > src > main > res > layout folder. Depends upon different resolutions, sometimes we may need to have it under layout > hdpi or layout > xhdpi folders, etc.
XML
<?xml version="1.0" encoding="utf-8"?><RelativeLayout     xmlns:android="http://schemas.android.com/apk/res/android"    xmlns:app="http://schemas.android.com/apk/res-auto"    xmlns:tools="http://schemas.android.com/tools"    android:layout_width="match_parent"    android:layout_height="match_parent"    tools:context=".MainActivity">      <ListView        android:id="@+id/listViewCountries"        android:layout_width="match_parent"        android:layout_height="match_parent"        android:background="@color/colorPrimaryDark"/>  </RelativeLayout>
Step 4: Working with the Java file
App Module.java file:
In Retrofit(Retrofit is a REST Client for Java and Android), we need the context object. To supply the objects, so here we will create this module that will give us the Context.
Java
import android.app.Application;import javax.inject.Singleton;import dagger.Module;import dagger.Provides;  @Moduleclass AppModule {    private Application mApplication;      AppModule(Application mApplication) {        this.mApplication = mApplication;    }      @Provides    @Singleton    Application provideApplication() {        return mApplication;    }}
With the dagger, we need to annotate @Singleton when we want a single instance only.
API Module.java:
For Retrofit, we need a bunch of things. Cache, Gson, OkHttpClient, and the Retrofit itself. So we will define the providers for these objects here in this module.
Gson: It is a Java library that can be used to convert Java Objects into their JSON representation.
Okhttp: works with Retrofit, which is a brilliant API for REST.
Java
import android.app.Application;import com.google.gson.FieldNamingPolicy;import com.google.gson.Gson;import com.google.gson.GsonBuilder;import javax.inject.Singleton;import dagger.Module;import dagger.Provides;import okhttp3.Cache;import okhttp3.OkHttpClient;import retrofit2.Retrofit;import retrofit2.converter.gson.GsonConverterFactory;  @Moduleclass ApiModule {      String mBaseUrl;      ApiModule(String mBaseUrl) {        this.mBaseUrl = mBaseUrl;    }        @Provides    @Singleton    Cache provideHttpCache(Application application) {        int cacheSize = 10 * 1024 * 1024;        Cache cache = new Cache(application.getCacheDir(), cacheSize);        return cache;    }      @Provides    @Singleton    Gson provideGson() {        GsonBuilder gsonBuilder = new GsonBuilder();        gsonBuilder.setFieldNamingPolicy(FieldNamingPolicy.LOWER_CASE_WITH_UNDERSCORES);        return gsonBuilder.create();    }      @Provides    @Singleton    OkHttpClient provideOkhttpClient(Cache cache) {        OkHttpClient.Builder client = new OkHttpClient.Builder();        client.cache(cache);        return client.build();    }      @Provides    @Singleton    Retrofit provideRetrofit(Gson gson, OkHttpClient okHttpClient) {        return new Retrofit.Builder()                .addConverterFactory(GsonConverterFactory.create(gson))                .baseUrl(mBaseUrl)                .client(okHttpClient)                .build();    }}
Building Component: ApiComponent.java
Java
import javax.inject.Singleton;import dagger.Component;  @Singleton@Component(modules = {AppModule.class, ApiModule.class})public interface ApiComponent {    void inject(MainActivity activity);}
We will inject in the MainActivity. We also define all the modules using the @Component annotation as we can see in the code.
MyApplication.java file:
Java
import android.app.Application;  public class MyApplication extends Application {      private ApiComponent mApiComponent;      @Override    public void onCreate() {        super.onCreate();        // https://restcountries.eu/rest/v2/all -> It will list all the country details        mApiComponent = DaggerApiComponent.builder()                .appModule(new AppModule(this))                .apiModule(new ApiModule("https://restcountries.eu/rest/v2/"))                .build();    }      public ApiComponent getNetComponent() {        return mApiComponent;    }}
MainActivity.java file:
Java
import android.os.Bundle;import android.widget.ArrayAdapter;import android.widget.ListView;import android.widget.Toast;import androidx.appcompat.app.AppCompatActivity;import java.util.List;import javax.inject.Inject;import retrofit2.Call;import retrofit2.Callback;import retrofit2.Response;import retrofit2.Retrofit;  public class MainActivity extends AppCompatActivity {      // injecting retrofit    @Inject Retrofit retrofit;    ListView listView;      @Override    protected void onCreate(Bundle savedInstanceState) {        super.onCreate(savedInstanceState);        setContentView(R.layout.activity_main);                    // injecting here        ((MyApplication) getApplication()).getNetComponent().inject(this);        listView = (ListView) findViewById(R.id.listViewCountries);        getCountries();    }      private void getCountries() {        Api api = retrofit.create(Api.class);                    // Call<List<Country>> call = RetrofitClient.getInstance().getMyApi().getCountries();        Call<List<Country>> call = api.getCountries();        call.enqueue(new Callback<List<Country>>() {            @Override            public void onResponse(Call<List<Country>> call, Response<List<Country>> response) {                List<Country> countryList = response.body();                  // Creating an String array for the ListView                String[] countries = new String[countryList.size()];                  // looping through all the countries and inserting                   // the names inside the string array                for (int i = 0; i < countryList.size(); i++) {                    countries[i] = countryList.get(i).getName();                }                  // displaying the string array into listview                listView.setAdapter(new ArrayAdapter<String>(getApplicationContext(), android.R.layout.simple_list_item_1, countries));            }              @Override            public void onFailure(Call<List<Country>> call, Throwable t) {                Toast.makeText(getApplicationContext(), t.getMessage(), Toast.LENGTH_SHORT).show();            }        });    }}
Example Request:
https://restcountries.eu/rest/v2/all will provide the output as shown in the image. We will take the country name from that
Example Response:
The output of the above REST API URL
As we are taking country names only we will get as a list like Afghanistan,.....India etc., On executing the above code, we can able to get the output as shown below.
You can find the source code: https://github.com/raj123raj/dagger-retrofit
android
Android
Java
Java
Android
Writing code in comment?
Please use ide.geeksforgeeks.org,
generate link and share the link here.
Comments
Old Comments
Retrofit with Kotlin Coroutine in Android
Android Listview in Java with Example
How to Read Data from SQLite Database in Android?
Flutter - Custom Bottom Navigation Bar
How to Change the Background Color After Clicking the Button in Android?
Arrays in Java
Split() String method in Java with examples
For-each loop in Java
Arrays.sort() in Java with examples
Initialize an ArrayList in Java