Android Dagger 2 + Retrofit + RecyclerView

Filed Under: Android

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.


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

android dagger2 retrofit recyclerview 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.


    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


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


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.


package com.journaldev.dagger2retrofitrecyclerview.di.qualifier;

import javax.inject.Qualifier;

@Qualifier
public @interface ActivityContext {

}


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.

android dagger2 retrofit recyclerview dependency graph

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


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


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


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.


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.


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


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


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:
android dagger2 retrofit recyclerview star wars api

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


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


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


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


<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.ConstraintLayout 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=".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


<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.ConstraintLayout 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=".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


<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://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.


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.


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.


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:


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.
android dagger2 recyclerview retrofit output

This brings an end to this tutorial. You can download the full source code from the link below.

Comments

  1. Nitesh Kumar Sharma says:

    In AdapterModule getClicklistener() provider returning wrong object.

    returning MainActivity

  2. kokoh says:

    Is it possible to directly parse arraylist data like this? public RecyleviewAdapter (List listmodel, Context context, ListAdapterCallback mAdapterCallback) {
    this.listmodel = listmodel;
    this.context = context;
    this.mAdapterCallback = mAdapterCallback;
    }
    how do I provide @provide depedencies for a Listmodel?

  3. Raj Sharma says:

    This is the best post about Dagger I HAVE EVER SEEN. So much in detail. Great job!

  4. User says:

    DaggerMainActivityComponent & DaggerDetailActivityComponent class not found?

  5. swaroop suthar says:

    Really useful. Answers a lot of my questions.

Leave a Reply

Your email address will not be published. Required fields are marked *

close
Generic selectors
Exact matches only
Search in title
Search in content
Search in posts
Search in pages