Using RxJava with Retrofit2
In this tutorial we will look how to use Retrofit2 and RxJava with each other. We will be using lambda expressions to reduce our boilerplate code. Have a look at this tutorial for setting up RetroLambda in your project.
Retrofit2
Retrofit is the library through which your API interfaces are turned into callable objects. By default, Retrofit will give you sane defaults for your platform but it allows for customization.
It lets you use annotations to describe HTTP requests. It offers other customization like:
- URL parameter replacement
- Query parameters
- Custom headers
- Multipart request body
- File uploads and downloads
In coming tutorials we’ll look at all of these in more detail.
Retrofit2 leverages OkHttp as the networking layer by default and is built on top of it. You don’t need to explicitly define OkHttp as a dependency for your project, unless you have a specific version requirement.
Preparing your project for Retrofit2
First of all we need to add dependency for retrofit2 in our app level build.gradle file. Retrofit2 requires a dependency for the automatic conversion of request and response payloads. Use the following dependencies if you’re using Retrofit2 and want JSON de-serialization using Gson:
1 2 3 4 5 |
//retroit compile 'com.squareup.retrofit2:retrofit:2.1.0' compile 'com.squareup.retrofit2:converter-gson:2.1.0' //rxjava adapter for retrofit2 compile 'com.squareup.retrofit2:adapter-rxjava:2.1.0' |
Since we are using RxJava with Retrofit2 in our project, we have to add dependency for its RxJava adapter also.
Also don’t forgot to add dependency for internet permission in AndroidManifest.xml
1 |
<uses-permission android:name="android.permission.INTERNET" /> |
Now your project is all set to use Retrofit2.
Adding RxJava related stuff
We are using RxJava along Retrofit2 so we need to add some dependecy of RxJava also. We have created tutorials for this earlier so please refer to then for setup:
You can have a look at some of RxJava samples so that its easy to understand in this tutorial also.
Using Retrofit2 in project
In this project we will be using sampe REST api from jsonplaceholder.typicode.com . We will be using following project structure in this tutorial.
Here packages are splitted based on functionality. All the networking related stuff is contained in networking package. api package contain all the endpoints which we will define in interface.
RetrofitProvider.java
First we have to create instance of Retrofit2 . This will be provided by RetrofitProvider.java class.
1 2 3 4 5 6 7 8 9 |
public class RetrofitProvider { public static Retrofit get() { return new Retrofit.Builder() .baseUrl("https://jsonplaceholder.typicode.com") .addConverterFactory(GsonConverterFactory.create()) .addCallAdapterFactory(RxJavaCallAdapterFactory.create()) .build(); } } |
This static method will provide Retrofit instance. We have to add base url where our server reside.
Next we have to add ConvertorFactory which is basically serialize/deserialize endpoint response to/from java objects(POJO). This means we will get response as java objects after using this adapter. The REST server we are using understand JSON so we will be using json convertor here.
RxJavaCallAdapterFactory is used to turn Retrofit endpoints to Observable streams so that we can hook RxJava subscribers.
Post.java
This is file which will be returned from endpoint which we are hitting.
Response from endpoint https://jsonplaceholder.typicode.com/posts will be like.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
[ { "userId": 1, "id": 1, "title": "sunt aut facere repellat provident occaecati excepturi optio reprehenderit", "body": "quia et suscipit\nsuscipit recusandae consequuntur expedita et cum\nreprehenderit molestiae ut ut quas totam\nnostrum rerum est autem sunt rem eveniet architecto" }, { "userId": 1, "id": 2, "title": "qui est esse", "body": "est rerum tempore vitae\nsequi sint nihil reprehenderit dolor beatae ea dolores neque\nfugiat blanditiis voluptate porro vel nihil molestiae ut reiciendis\nqui aperiam non debitis possimus qui neque nisi nulla" } ] |
This response will be returned when we make GET call to above listed url. This is basically a list of posts. In java notation this Post call will look like this.
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 |
public class Post { private int userId; private int id; private String title; private String body; public int getUserId() { return userId; } public void setUserId(int userId) { this.userId = userId; } public int getId() { return id; } public void setId(int id) { this.id = id; } 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; } } |
Its might look difficult at first but its very easy to create this object. I use very good plugin which will convert your json to POJO directly in IDE itself. Install this plugin and easily convert JSON to POJO by just pasting JSON data.
JsonPlaceHolderApi.java
In this file we will create all endpoint methods using Annotations which will get us data. These methods will return Observable of type List<Post>.
1 2 3 4 |
public interface JsonPlaceHolderApi { @GET("posts") Observable<List<Post>> getPosts(); } |
Here @GET tells retrofit that its a GET type request and “post” inside get tells that it will hit at endpoint named /post. So it make final endpoint https://jsonplaceholder.typicode.com/posts .
Hooking all things up
Now its time to wire all things up PostActivity.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 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 |
public class PostsActivity extends AppCompatActivity { private RecyclerView recyclerView; private JsonPlaceHolderApi api; private AllPostsAdapter adapter; private ProgressDialog progress; private Subscription subscription; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_posts); progress = new ProgressDialog(this); progress.setMessage("Loading..."); //initialize adapter adapter = new AllPostsAdapter(); //reference recycler view recyclerView = (RecyclerView) findViewById(R.id.recycler_view); //setup layout manager recyclerView.setLayoutManager(new LinearLayoutManager(this)); //set adapter to recycler view recyclerView.setAdapter(adapter); //create api object from retrofit api = RetrofitProvider.get().create(JsonPlaceHolderApi.class); //get all posts subscription = api.getPosts().subscribeOn(Schedulers.io()) //setting up worker thread .observeOn(AndroidSchedulers.mainThread()) //setting up thread where result will be delivered .doOnSubscribe(() -> progress.show()) //show progress bar on subscribe .doOnCompleted(() -> progress.dismiss()) //dismiss progress bar on complete .subscribe(posts -> { //result will be delivered here adapter.setData(posts); //sending api result to recycler adapter }, err -> { //error from api comes here err.printStackTrace(); //printing stack trace in case of err progress.dismiss(); //hiding progressbar as onComplete is not called in case of error }); } @Override protected void onDestroy() { super.onDestroy(); subscription.unsubscribe(); } } |
In this activity we are hitting endpoint and when data is available then we show it inside a RecyclerView. First of all we have to instainitate JsonPlaceHolderApi which we are doing on Line 28 using JsonPlaceHolderApi interface. Now we can call methods on this object.
Next on Line 31 we are calling getPost() method on JsonPlaceHolderApi interface. Since in Android network calls should be done on another thread so we have tell RxJava to do this work on some worker thread. This is done in Line 31 itself using subscribeOn(Schedulers.io()).
On Line 32,33 we are telling RxJava to deliver its result on Main thread. Next comes doOnSubscribe() and doOnComplete() these methods will be called on start and end of network call respectively. We are just showing and dismissing the loader with this so that user might get updated that something is happening. We have used lambdas here you can refer to this tutorial if you are having any confusion.
At last comes the subscribe() method, this is where the result is delivered. This method is Overridden so there are many implementations. We are using implementation which delivers final result and error[if any]. If result is delivered then we will get List of posts in first argument of method else there was en error. In case of error we have dismiss progressDialog. Here also lambda, please refer this in case of any confusion.
At last, subscribe() method return a subscription which can be used to dismiss this call at any time by calling subscription.unsubscribe(). Which we are calling in onDestroy().
Rest of the implementation is handled in RecyclerView and its adapter. This is all you need to know in this tutorial.
Please let me know if you have any confusion in this tutorial.