This is the one stop complete tutorial for implementing Dagger 2 with Retrofit and RecyclerView in our Android Application.
Dagger 2 is a dependency injection library that’s vital for clean code and architecture. For a basic overview of Dependency Injection and Dagger 2 refer this tutorial before proceeding ahead.
What is Dependency Injection?
Dependency Injection simply put, instead of creating instances yourself using the new keyword, you’ll be provided those instances from outside.
Dependency Injection is our friend in the worst and best times. It helps in refactoring the code quickly and helps in testing individual things since nothing is tightly coupled. It enhances the readability and maintainability.
Regardless, of the knowledge of Dependency Injection, at some point in your Object Oriented Programming, you have definitely used it. Following example will definitely remind you of it.
1 2 3 4 5 6 7 8 9 10 11 |
public class A { public static void main(String[] args){ B b = new B(); C c = new C(b); D d = new D(b, c); E e = new E(d, b); A a = new A(e, b); } } |
Class A is a dependent. Class E and B are dependencies that are injected.
As you can see in the above code, instead of initializing classes in the constructors, we do them separately. Though we still have the boilerplate code above.
Important Points to note about Dagger 2
- It checks and draws the dependency object graph at compile-time.
- We need to use the annotations :
@Module
,@Provides
,@Inject
,@Component
@Scope
. - For two dependencies that conflict, such as Application has a different Context and an Activity has a different. Dagger 2 needs
@Qualifier
our@Named
annotations to differentiate. @Component
is set on an interface. It acts as a bridge and is used to provide the dependencies specified in the@Module
to the Java class. The dependency would be retrieved with@Inject
in our Java class.- Dagger 2 cannot inject private fields.
Dagger 2 is best understood through an example. It’s been a while and we’ve tried to create an Android Application that explains the concepts in the best possible way using RecyclerView and Retrofit.
We’ll be using the StarWars API.
Let’s dive deep!
Project Structure
That’s big! We created a separate package di
for dependency injection components, modules, scopes and qualifiers. The activities go into the ui
package. The API method and POJO class are inside the retrofit
and pojo
packages respectively. The adapter
holds the RecyclerViewAdapter class.
This project consists of two activities – MainActivity and DetailActivity.
Add the following library dependencies inside the app’s build.gradle
.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
implementation 'com.android.support:design:27.1.0' implementation group: 'com.google.code.gson', name: 'gson', version: '2.8.2' implementation group: 'com.squareup.retrofit2', name: 'converter-gson', version: '2.3.0' implementation group: 'com.squareup.okhttp3', name: 'okhttp', version: '3.10.0' implementation group: 'com.squareup.okhttp3', name: 'logging-interceptor', version: '3.9.0' implementation group: 'com.google.code.gson', name: 'gson', version: '2.8.2' implementation(group: 'com.squareup.retrofit2', name: 'retrofit', version: '2.3.0') { exclude module: 'okhttp' } implementation 'com.google.dagger:dagger-android:2.11' implementation 'com.google.dagger:dagger-android-support:2.11' annotationProcessor 'com.google.dagger:dagger-android-processor:2.11' annotationProcessor 'com.google.dagger:dagger-compiler:2.13' |
Ensure that you’ve added the the Internet Permissions in your AndroidManifest file.
Dependency Injection package
scopes
Scopes define where all those Components would be used. In this application, their are two : ActivityScope and ApplicationScope.
ActivityScope.java
1 2 3 4 5 6 7 8 9 10 |
package com.journaldev.dagger2retrofitrecyclerview.di.scopes; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import javax.inject.Scope; @Scope @Retention(RetentionPolicy.CLASS) public @interface ActivityScope { } |
ApplicationScope.java
1 2 3 4 5 6 7 8 9 10 |
package com.journaldev.dagger2retrofitrecyclerview.di.scopes; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import javax.inject.Scope; @Scope @Retention(RetentionPolicy.CLASS) public @interface ApplicationScope { } |
@ActivityScope and @ApplicationScope would be used on the Components later on.
qualifiers
So, a Context can be either of the Activity or the Application. How would Dagger2 differentiate between them?
Using Qualifiers.
The ActivityContext.java and the ApplicationContext.java classes are defined below.
1 2 3 4 5 6 7 |
package com.journaldev.dagger2retrofitrecyclerview.di.qualifier; import javax.inject.Qualifier; @Qualifier public @interface ActivityContext { } |
1 2 3 4 5 6 7 |
package com.journaldev.dagger2retrofitrecyclerview.di.qualifier; import javax.inject.Qualifier; @Qualifier public @interface ApplicationContext { } |
Now in the Modules wherever we use Context, we must annotate it with @ApplicationContext or @ActivityContext depending on the use case.
Modules
Modules are what would provide the dependencies to the dependents via Components.
Let’s plan out our Dependency Graph first.
So the APIInterface
isn’t dependent on anything.
The ApplicationComponent would hold the Retrofit and AppContext Modules.
The MainActivity would hold the Adapter and Activity Context Modules along with the ApplicationComponent’s dependencies.
The DetailActivityComponent doesn’t include any of its own modules. It just uses the ones present in the ApplicationComponent.
ContextModule
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 |
package com.journaldev.dagger2retrofitrecyclerview.di.module; import android.content.Context; import com.journaldev.dagger2retrofitrecyclerview.di.qualifier.ApplicationContext; import com.journaldev.dagger2retrofitrecyclerview.di.scopes.ApplicationScope; import dagger.Module; import dagger.Provides; @Module public class ContextModule { private Context context; public ContextModule(Context context) { this.context = context; } @Provides @ApplicationScope @ApplicationContext public Context provideContext() { return context; } } |
We’ve specified the Application Level scope and qualifier for the context.
RetrofitModule
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 |
package com.journaldev.dagger2retrofitrecyclerview.di.module; import com.journaldev.dagger2retrofitrecyclerview.di.scopes.ApplicationScope; import com.journaldev.dagger2retrofitrecyclerview.retrofit.APIInterface; import dagger.Module; import dagger.Provides; import okhttp3.OkHttpClient; import okhttp3.logging.HttpLoggingInterceptor; import retrofit2.Retrofit; import retrofit2.converter.gson.GsonConverterFactory; @Module public class RetrofitModule { @Provides @ApplicationScope APIInterface getApiInterface(Retrofit retroFit) { return retroFit.create(APIInterface.class); } @Provides @ApplicationScope Retrofit getRetrofit(OkHttpClient okHttpClient) { return new Retrofit.Builder() .baseUrl("https://swapi.co/api/") .addConverterFactory(GsonConverterFactory.create()) .client(okHttpClient) .build(); } @Provides @ApplicationScope OkHttpClient getOkHttpCleint(HttpLoggingInterceptor httpLoggingInterceptor) { return new OkHttpClient.Builder() .addInterceptor(httpLoggingInterceptor) .build(); } @Provides @ApplicationScope HttpLoggingInterceptor getHttpLoggingInterceptor() { HttpLoggingInterceptor httpLoggingInterceptor = new HttpLoggingInterceptor(); httpLoggingInterceptor.setLevel(HttpLoggingInterceptor.Level.BODY); return httpLoggingInterceptor; } } |
@Provides denotes that a dependency would be provided from that method to it’s dependents.
For Retrofit we use an ApplicationScope.
MainActivityContextModule
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 |
package com.journaldev.dagger2retrofitrecyclerview.di.module; import android.content.Context; import com.journaldev.dagger2retrofitrecyclerview.di.qualifier.ActivityContext; import com.journaldev.dagger2retrofitrecyclerview.di.scopes.ActivityScope; import com.journaldev.dagger2retrofitrecyclerview.ui.MainActivity; import dagger.Module; import dagger.Provides; @Module public class MainActivityContextModule { private MainActivity mainActivity; public Context context; public MainActivityContextModule(MainActivity mainActivity) { this.mainActivity = mainActivity; context = mainActivity; } @Provides @ActivityScope public MainActivity providesMainActivity() { return mainActivity; } @Provides @ActivityScope @ActivityContext public Context provideContext() { return context; } } |
The above module is used to provide the Activity Context and the Activity’s instance.
AdapterModule
The code for the AdapterModule is given below.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 |
package com.journaldev.dagger2retrofitrecyclerview.di.module; import com.journaldev.dagger2retrofitrecyclerview.adapter.RecyclerViewAdapter; import com.journaldev.dagger2retrofitrecyclerview.di.scopes.ActivityScope; import com.journaldev.dagger2retrofitrecyclerview.ui.MainActivity; import dagger.Module; import dagger.Provides; @Module(includes = {MainActivityContextModule.class}) public class AdapterModule { @Provides @ActivityScope public RecyclerViewAdapter getStarWarsPeopleLIst(RecyclerViewAdapter.ClickListener clickListener) { return new RecyclerViewAdapter(clickListener); } @Provides @ActivityScope public RecyclerViewAdapter.ClickListener getClickListener(MainActivity mainActivity) { return mainActivity; } } |
It’s used to create the RecyclerViewAdapter from the POJO data.
Also, the ClickListener is an interface defined in the RecyclerViewAdapter class to trigger the click listener callback methods from the Activity itself.
It injects the MainActivity dependency since we’ve included the MainActivityContextModule
in the definition.
Let’s look at the APIInterface and the POJO classes.
The code for the APIInterface.java class is given below.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
package com.journaldev.dagger2retrofitrecyclerview.retrofit; import com.journaldev.dagger2retrofitrecyclerview.pojo.Film; import com.journaldev.dagger2retrofitrecyclerview.pojo.StarWars; import retrofit2.Call; import retrofit2.http.GET; import retrofit2.http.Query; import retrofit2.http.Url; public interface APIInterface { @GET("people/?") Call<StarWars> getPeople(@Query("format") String format); @GET Call<Film> getFilmData(@Url String url, @Query("format") String format); } |
@Url
is used to do a dynamic URL call in Retrofit. The URL would be specified at runtime.
The POJO classes are created from the .jsonschema2pojo.
StarWars.java
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 |
package com.journaldev.dagger2retrofitrecyclerview.pojo; import com.google.gson.annotations.SerializedName; import java.util.List; public class StarWars { @SerializedName("results") public List<People> results = null; public class People { @SerializedName("name") public String name; @SerializedName("height") public String height; @SerializedName("mass") public String mass; @SerializedName("birth_year") public String birthYear; @SerializedName("gender") public String gender; @SerializedName("homeworld") public String homeworld; @SerializedName("films") public List<String> films = null; } } |
Film.java
1 2 3 4 5 6 7 8 9 10 |
package com.journaldev.dagger2retrofitrecyclerview.pojo; import com.google.gson.annotations.SerializedName; public class Film { @SerializedName("title") public String title; @SerializedName("director") public String director; } |
We’re only parsing the values which we’ll be using in our application.
The star wars api looks like this:
Components
In the Components, we’ll include the Modules.
We’ll need to expose the fields that’ll be used in our Activity/Application.
ApplicationComponent.java
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 |
package com.journaldev.dagger2retrofitrecyclerview.di.component; import android.content.Context; import com.journaldev.dagger2retrofitrecyclerview.MyApplication; import com.journaldev.dagger2retrofitrecyclerview.di.module.ContextModule; import com.journaldev.dagger2retrofitrecyclerview.di.module.RetrofitModule; import com.journaldev.dagger2retrofitrecyclerview.di.qualifier.ApplicationContext; import com.journaldev.dagger2retrofitrecyclerview.di.scopes.ApplicationScope; import com.journaldev.dagger2retrofitrecyclerview.retrofit.APIInterface; import dagger.Component; @ApplicationScope @Component(modules = {ContextModule.class, RetrofitModule.class}) public interface ApplicationComponent { public APIInterface getApiInterface(); @ApplicationContext public Context getContext(); public void injectApplication(MyApplication myApplication); } |
Dagger2 would autogenerate a class named Dagger%ComponentName%. Eg. DaggerApplicationComponent.
injectApplication
is used to allow @Inject fields in our Activity/Application.
MainActivityComponent.java
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
package com.journaldev.dagger2retrofitrecyclerview.di.component; import android.content.Context; import com.journaldev.dagger2retrofitrecyclerview.di.module.AdapterModule; import com.journaldev.dagger2retrofitrecyclerview.di.qualifier.ActivityContext; import com.journaldev.dagger2retrofitrecyclerview.di.scopes.ActivityScope; import com.journaldev.dagger2retrofitrecyclerview.ui.MainActivity; import dagger.Component; @ActivityScope @Component(modules = AdapterModule.class, dependencies = ApplicationComponent.class) public interface MainActivityComponent { @ActivityContext Context getContext(); void injectMainActivity(MainActivity mainActivity); } |
The above component would have access to the ApplicationComponent dependencies too.
DetailActivityComponent.java
1 2 3 4 5 6 7 8 9 10 11 |
package com.journaldev.dagger2retrofitrecyclerview.di.component; import com.journaldev.dagger2retrofitrecyclerview.di.scopes.ActivityScope; import com.journaldev.dagger2retrofitrecyclerview.ui.DetailActivity; import dagger.Component; @Component(dependencies = ApplicationComponent.class) @ActivityScope public interface DetailActivityComponent { void inject(DetailActivity detailActivity); } |
Now is the time to use the di in our Activity’s and Application.
Let’s look at the layout codes first.
Layout
activity_main.xml
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
<?xml version="1.0" encoding="utf-8"?> <android.support.constraint.ConstraintLayout xmlns:android="https://schemas.android.com/apk/res/android" xmlns:app="https://schemas.android.com/apk/res-auto" xmlns:tools="https://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" tools:context=".ui.MainActivity"> <android.support.v7.widget.RecyclerView android:id="@+id/recyclerView" android:layout_width="match_parent" android:layout_height="match_parent" /> </android.support.constraint.ConstraintLayout> |
activity_detail.xml
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 |
<?xml version="1.0" encoding="utf-8"?> <android.support.constraint.ConstraintLayout xmlns:android="https://schemas.android.com/apk/res/android" xmlns:app="https://schemas.android.com/apk/res-auto" xmlns:tools="https://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" tools:context=".ui.DetailActivity"> <TextView android:id="@+id/textView" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="Loading..." android:textColor="@android:color/black" android:textSize="28sp" android:gravity="center" app:layout_constraintBottom_toBottomOf="parent" app:layout_constraintLeft_toLeftOf="parent" app:layout_constraintRight_toRightOf="parent" app:layout_constraintTop_toTopOf="parent" /> </android.support.constraint.ConstraintLayout> |
recycler_view_list_row.xml
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 |
<?xml version="1.0" encoding="utf-8"?> <android.support.constraint.ConstraintLayout xmlns:android="https://schemas.android.com/apk/res/android" xmlns:app="https://schemas.android.com/apk/res-auto" android:id="@+id/constraintLayout" android:layout_width="match_parent" android:layout_height="wrap_content" android:padding="16dp"> <TextView android:id="@+id/txtName" android:layout_width="wrap_content" android:layout_height="wrap_content" /> <TextView android:id="@+id/txtBirthYear" android:layout_width="wrap_content" android:layout_height="wrap_content" app:layout_constraintTop_toBottomOf="@+id/txtName" /> </android.support.constraint.ConstraintLayout> |
Before we use dependency injection in our classes, REBUILD THE PROJECT. This is done to generate the Dagger Component classes.
The code for the MyApplication.java class is given below.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 |
package com.journaldev.dagger2retrofitrecyclerview; import android.app.Activity; import android.app.Application; import com.journaldev.dagger2retrofitrecyclerview.di.component.ApplicationComponent; import com.journaldev.dagger2retrofitrecyclerview.di.component.DaggerApplicationComponent; import com.journaldev.dagger2retrofitrecyclerview.di.module.ContextModule; public class MyApplication extends Application { ApplicationComponent applicationComponent; @Override public void onCreate() { super.onCreate(); applicationComponent = DaggerApplicationComponent.builder().contextModule(new ContextModule(this)).build(); applicationComponent.injectApplication(this); } public static MyApplication get(Activity activity){ return (MyApplication) activity.getApplication(); } public ApplicationComponent getApplicationComponent() { return applicationComponent; } } |
DaggerApplicationComponent.builder().contextModule(new ContextModule(this)).build();
is used to build the modules present in the component.
getApplicationComponent would be used to return the ApplicationComponent in our Activities.
Don’t forget to add the above application in our AndroidManifest.xml file.
UI package
The code for the MainActivity.java class is given below.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 |
package com.journaldev.dagger2retrofitrecyclerview.ui; import android.content.Context; import android.content.Intent; import android.support.v7.app.AppCompatActivity; import android.os.Bundle; import android.support.v7.widget.LinearLayoutManager; import android.support.v7.widget.RecyclerView; import android.widget.Toast; import com.journaldev.dagger2retrofitrecyclerview.MyApplication; import com.journaldev.dagger2retrofitrecyclerview.R; import com.journaldev.dagger2retrofitrecyclerview.adapter.RecyclerViewAdapter; import com.journaldev.dagger2retrofitrecyclerview.di.component.ApplicationComponent; import com.journaldev.dagger2retrofitrecyclerview.di.component.DaggerMainActivityComponent; import com.journaldev.dagger2retrofitrecyclerview.di.component.MainActivityComponent; import com.journaldev.dagger2retrofitrecyclerview.di.module.MainActivityContextModule; import com.journaldev.dagger2retrofitrecyclerview.di.qualifier.ActivityContext; import com.journaldev.dagger2retrofitrecyclerview.di.qualifier.ApplicationContext; import com.journaldev.dagger2retrofitrecyclerview.pojo.StarWars; import com.journaldev.dagger2retrofitrecyclerview.retrofit.APIInterface; import java.util.List; import javax.inject.Inject; import retrofit2.Call; import retrofit2.Callback; import retrofit2.Response; public class MainActivity extends AppCompatActivity implements RecyclerViewAdapter.ClickListener { private RecyclerView recyclerView; MainActivityComponent mainActivityComponent; @Inject public RecyclerViewAdapter recyclerViewAdapter; @Inject public APIInterface apiInterface; @Inject @ApplicationContext public Context mContext; @Inject @ActivityContext public Context activityContext; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); recyclerView = findViewById(R.id.recyclerView); recyclerView.setLayoutManager(new LinearLayoutManager(MainActivity.this)); ApplicationComponent applicationComponent = MyApplication.get(this).getApplicationComponent(); mainActivityComponent = DaggerMainActivityComponent.builder() .mainActivityContextModule(new MainActivityContextModule(this)) .applicationComponent(applicationComponent) .build(); mainActivityComponent.injectMainActivity(this); recyclerView.setAdapter(recyclerViewAdapter); apiInterface.getPeople("json").enqueue(new Callback<StarWars>() { @Override public void onResponse(Call<StarWars> call, Response<StarWars> response) { populateRecyclerView(response.body().results); } @Override public void onFailure(Call<StarWars> call, Throwable t) { } }); } private void populateRecyclerView(List<StarWars.People> response) { recyclerViewAdapter.setData(response); } @Override public void launchIntent(String url) { Toast.makeText(mContext, "RecyclerView Row selected", Toast.LENGTH_SHORT).show(); startActivity(new Intent(activityContext, DetailActivity.class).putExtra("url", url)); } } |
Once this happens: mainActivityComponent.injectMainActivity(this);
, The fields present with the @Inject
would be automatically injected.
The rest is doing a Retrofit call and setting the data in the RecyclerViewAdapter.
The class implements the RecyclerViewAdapter.ClickListener
interface callback which triggers a launchIntent method whenever the RecyclerView row gets clicked.
Note that the Context injected needs to be specified with the relevant qualifier we had earlier defined.
The code for the RecyclerViewAdapter is given below.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 |
package com.journaldev.dagger2retrofitrecyclerview.adapter; import android.support.constraint.ConstraintLayout; import android.support.v7.widget.RecyclerView; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; import android.widget.TextView; import com.journaldev.dagger2retrofitrecyclerview.R; import com.journaldev.dagger2retrofitrecyclerview.pojo.StarWars; import java.util.ArrayList; import java.util.List; import javax.inject.Inject; public class RecyclerViewAdapter extends RecyclerView.Adapter<RecyclerViewAdapter.ViewHolder> { private List<StarWars.People> data; private RecyclerViewAdapter.ClickListener clickListener; @Inject public RecyclerViewAdapter(ClickListener clickListener) { this.clickListener = clickListener; data = new ArrayList<>(); } @Override public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) { return new ViewHolder(LayoutInflater.from(parent.getContext()).inflate(R.layout.recycler_view_list_row, parent, false)); } @Override public void onBindViewHolder(ViewHolder holder, int position) { holder.txtName.setText(data.get(position).name); holder.txtBirthYear.setText(data.get(position).birthYear); } @Override public int getItemCount() { return data.size(); } class ViewHolder extends RecyclerView.ViewHolder { private TextView txtName; private TextView txtBirthYear; private ConstraintLayout constraintLayoutContainer; ViewHolder(View itemView) { super(itemView); txtName = itemView.findViewById(R.id.txtName); txtBirthYear = itemView.findViewById(R.id.txtBirthYear); constraintLayoutContainer = itemView.findViewById(R.id.constraintLayout); constraintLayoutContainer.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { clickListener.launchIntent(data.get(getAdapterPosition()).films.get(0)); } }); } } public interface ClickListener { void launchIntent(String filmName); } public void setData(List<StarWars.People> data) { this.data.addAll(data); notifyDataSetChanged(); } } |
The code for the DetailActivity.java class is given below:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 |
package com.journaldev.dagger2retrofitrecyclerview.ui; import android.content.Context; import android.os.Bundle; import android.support.v7.app.AppCompatActivity; import android.widget.TextView; import com.journaldev.dagger2retrofitrecyclerview.MyApplication; import com.journaldev.dagger2retrofitrecyclerview.R; import com.journaldev.dagger2retrofitrecyclerview.di.component.ApplicationComponent; import com.journaldev.dagger2retrofitrecyclerview.di.component.DaggerDetailActivityComponent; import com.journaldev.dagger2retrofitrecyclerview.di.component.DetailActivityComponent; import com.journaldev.dagger2retrofitrecyclerview.di.qualifier.ApplicationContext; import com.journaldev.dagger2retrofitrecyclerview.pojo.Film; import com.journaldev.dagger2retrofitrecyclerview.retrofit.APIInterface; import javax.inject.Inject; import retrofit2.Call; import retrofit2.Callback; import retrofit2.Response; public class DetailActivity extends AppCompatActivity { DetailActivityComponent detailActivityComponent; @Inject public APIInterface apiInterface; @Inject @ApplicationContext public Context mContext; TextView textView; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_detail); textView = findViewById(R.id.textView); String url = getIntent().getStringExtra("url"); ApplicationComponent applicationComponent = MyApplication.get(this).getApplicationComponent(); detailActivityComponent = DaggerDetailActivityComponent.builder() .applicationComponent(applicationComponent) .build(); detailActivityComponent.inject(this); apiInterface.getFilmData(url, "json").enqueue(new Callback<Film>() { @Override public void onResponse(Call<Film> call, Response<Film> response) { Film films = response.body(); String text = "Film name:n" + films.title + "nDirector:n" + films.director; textView.setText(text); } @Override public void onFailure(Call<Film> call, Throwable t) { } }); } } |
Again the inject
method is used to inject all the dependency fields.
The retrofit makes a request to the dynamic URL specified and displays the response in a TextView.
The output of the above application in action is given below.
This brings an end to this tutorial. You can download the full source code from the link below.