How to use Rxjava with Dagger2 and Retrofit and OkHttp and Gson
In this article we will see how to create a complete project using rxjava, dagger2, retrofit, okhttp and Gson
Click here to Download or look at Source code of this example from github
First let's illustrate basic structure of each library
Dagger2
To use dagger you must consider that there are three component must implemented
- Module (or more): this is classes which will provide objects
- Component (or more): this is interface link between providers and injectable objects (classes which consume object that module provides)
- Injectable object (Usually Activity, but it could be any thing else)
Those points will be clear enough at implementation part.
Rxjava
RxJava also consist of 3 components
- Observable : Object with heavy process (like http request and response)
- Scheduler: specify in which process will observable execute its process and in which process results will given
- Subscriber: object will receive results from observable after finishing it's job.
Retrofit
you can take a look at this article https://www.garudax.id/pulse/retrofit-rxjava-eslam-ahmad, to see how to use retrofit
OkHTTP and Gson: Just builders will used in this article
Example Structure
We need to inject Retrofit object to our main activity class, also Retrofit object need some other dependencies like
- Base Url
- Gson converter object
- HTTP object
Http object also need dependencies like Application object to add cache.
So i will create 2 Modules, one will provide retrofit and http and gson, i will name it NetModule, and one to provide application and i will name it ApplicationModule.
As i mentioned (in dagger structure) we need Component interface i will name it NetComponent
Then Retrofit need
- Api interface that will handle http requests, in this example i will name it RestApi
- POJO classes for single item (in this example it will be only one class it's name will be Post)
And for Android we need:
- Application Class which will handle component initialization, i will name it App
- Activity, i will name it MainActivity
Let's start implementing our project
After creating a new project you will need to add necessary dependency
//RxJava
compile 'io.reactivex.rxjava2:rxandroid:2.0.1'
compile 'io.reactivex.rxjava2:rxjava:2.1.7'
// Retrofit
compile 'com.squareup.retrofit2:retrofit:2.3.0'
//RxJava and Retrofit integrantion
compile 'com.jakewharton.retrofit:retrofit2-rxjava2-adapter:1.0.0'
// gson
compile 'com.google.code.gson:gson:2.8.0'
//gson and retrofit integration
compile 'com.squareup.retrofit2:converter-gson:2.3.0'
//dagger
compile 'com.google.dagger:dagger:2.14.1'
annotationProcessor 'com.google.dagger:dagger-compiler:2.14.1'
//OkHttp
compile 'com.squareup.okhttp3:okhttp:3.2.0'
compile 'com.squareup.okio:okio:1.7.0'
1- Create NetModule (Which will provide Retrofit, OkHttp, Gson).
@Module
public class NetModule {
private String baseUrl;
public NetModule(String baseUrl) {
this.baseUrl = baseUrl;
}
@Provides OkHttpClient provideHttpClient(Cache cache){
OkHttpClient.Builder client = new OkHttpClient.Builder();
client.cache(cache);
return client.build();
}
@Provides Cache provideCache(Application application){
int cacheSize = 1024*1024*10;
return new Cache(application.getCacheDir(),cacheSize);
}
@Provides Gson provideGson(){
GsonBuilder gsonBuilder = new GsonBuilder();
gsonBuilder.setFieldNamingPolicy(FieldNamingPolicy.LOWER_CASE_WITH_UNDERSCORES);
return gsonBuilder.create();
}
@Provides Retrofit provideRetrofit(Gson gson,OkHttpClient client){
return new Retrofit.Builder()
.addConverterFactory(GsonConverterFactory.create(gson))
.addCallAdapterFactory(RxJava2CallAdapterFactory.create())
.baseUrl(baseUrl)
.build();
}
}
Because it is a module it will inject all methods params if it available!
If you looked to provideRetrofit method it need Gson object and OkHttpClient object as parameters and there are two methods provide those items so Dagger will inject it automatically.
But there are function named provideCache need Application object which not exist in this class
so let's create ApplicationModule class
@Module
public class ApplicationModule {
private Application application;
public ApplicationModule(Application application) {
this.application = application;
}
@Provides Application provideApplication(){
return application;
}
}
When we link those Modules provideCache will take it's dependencies by default.
Lets make the interface that will link modules with injectable object.
@Component (modules = {ApplicationModule.class,NetModule.class})
public interface NetComponent {
void injectMainActivity(MainActivity mainActivity);
}
This interface will make link between Application module and NetModule, and will make MainActivity injectable.
Then we must build Dagger object so from build menu click make project after finishing
create a new class named App extends Application class
public class App extends Application {
NetComponent netComponent;
@Override
public void onCreate() {
super.onCreate();
netComponent = DaggerNetComponent.builder()
.applicationModule(new ApplicationModule(this))
.netModule(new NetModule("https://jsonplaceholder.typicode.com/"))
.build();
}
public NetComponent getNetComponent(){
return netComponent;
}
}
Please note that "https://jsonplaceholder.typicode.com/" is the api base url.
then you must add App class to manifest file
<application android:name=".App"
and at MainActivity class you can add this line
((App) getApplication()).getNetComponent().injectMainActivity(this);
At this point Dagger is implemented and ready to do it's job.
Let's finish this by create Retrofit classes (POJO and Interface)
POJO object
public class Post {
private String title;
private String body;
public String getTitle() {
return title;
}
public void setTitle(String title) {
this.title = title;
}
public String getBody() {
return body;
}
public void setBody(String body) {
this.body = body;
}
}
Interface
public interface RestApi {
@GET("/posts")
Observable<List<Post>> getPosts();
}
Here we go, Every thing is ready let's test our work
public class MainActivity extends AppCompatActivity {
@Inject Retrofit retrofit;//Auto Inject Retrofit from NetModule
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
((App) getApplication()).getNetComponent().injectMainActivity(this); //Link Main activity with modules through component
Observable<List<Post>> call = retrofit.create(RestApi.class).getPosts();//get observable posts list from api
//Observer which will take result from observable object
Observer<List<Post>> observer = new Observer<List<Post>>() {
@Override
public void onSubscribe(Disposable d) {
}
@Override
public void onNext(List<Post> posts) {
for(Post post : posts){
Log.i("TEST",post.getTitle()); //Write post title at log
}
}
@Override
public void onError(Throwable e) {
e.printStackTrace();
}
@Override
public void onComplete() {
}
};
call.subscribeOn(Schedulers.io())//run http get request at io Thread
.observeOn(AndroidSchedulers.mainThread()) //get result at main Thread
.subscribe(observer);//Fire observable
}
}
Click here to Download or look at Source code of this example from github
Thank you so much Eslam. I was having a lot of trouble trying to understand how to use Dagger 2 with RxJava. It´s all clear now, thanks to you and your good will to teach others. Have a good day.
Why you set provideHttpClient @Reusable in NetModule