- Retrofit and rxjava android
- Retrofit Rxjava Android Example
- Setup
- Retrofit Rxjava
- Retrofit Rxjava Multiple Calls and Examples
- Retrofit Rxjava Android Example
- Add dependencies and permissions
- Retrofit Interface
- Activity
- RecyclerView Adapter
- RecyclerView Item Layout
- About
- Retrofit. Query, Path, RxJava, логи
- Разделение ссылки
- Query
- Логирование
- RxJava
- Как получить чистый текст
- Как сделать синхронный вызов
- Android RxJava Networking with Retrofit, Gson – Notes App
- 1. Prerequisite
- 2. App Design
- 3. Notes REST API
- 4. Creating New Project
- 4.1 Adding Retrofit Network Layer
- 4.2 Adding Main Interface
Retrofit and rxjava android
Retrofit Rxjava Android Example
June 22, 2017 by Srinivas
Using retrofit and rxjava, you can easily develop components to get data from reset services and update view objects with results from background process.
Retrofit is an http client using which you can build easy to maintain and enhance rest clients. With retrofit, you don’t need to use low level http objects in your code, all you need to do is to define interface for your service call, configure retrofit builder and set required converters and adapters.
RxJava and RxAndroid allow you to build backend components in android, which can execute multiple reset service calls parallel, chain service calls, process results, and update view object in main thread by utilizing RxJava features such schedulers, observeOn, subscribeOn and other operators.
You can learn more about Rxjava by reading RxJava examples and Rxjava operators posts.
Setup
You need to add below dependencies to use retrofit and rxjava in android.
Retrofit Rxjava
Retrofit services can return any type of object, but to make retrofit support the type of object you want in your project, you need to provide adapters. Retrofit rxjava adapter makes retrofit return observables.
Notice that one of the library dependency mentioned above is retrofit rxjava adapter.
You can set adapter by calling addCallAdapterFactory method on Retrofit.Builder using RxJava2CallAdapterFactory class.
After this setup, retrofit service call can return rxjava observable objects. So, next step in using retrofit with rxjava is to define service interface which returns observable.
Finally make a call to service that runs in the background and updates UI with results on android main thread. SubscribeOn makes it run in the background thread and observeOn is what makes it possible to return the execution to main thread to execute subscriber code and update view objects with results from service call. RxAndroid provides AndroidSchedulers class that can get hold of android main thread, on which subscriber gets results.
Retrofit Rxjava Multiple Calls and Examples
In the case of single retrofit service call, you can directly subscribe to the observable returned by the retrofit service and process results. But if you need to make multiple services call to full fill data needs of a user request, you will have to use RxJava operators to transform, combine, and merger results.
Let’s go over few scenarios where multiple retrofit service calls are made parallel or results from service calls are transformed, modified, or merged using rxjava operators.
Making two service calls parallel and combining results using retrofit and rxjava.
Making second service call based on results from first service call using retrofit and rxjava. Function supplied to flatMap makes first retrofit service call, map is applied on resulting observable from the service call to get response and then again flatMap is used to make a second service call using data from previous service call and consumer is subscribed to final observable.
You can transform or modify response from retrofit service call using rxjava operators. In below example, map operator is used to modify value of response.
If you want to filter some records from the response received from retrofit service call, you can use filter operator. In the below example, first it makes a call to retrofit service, then flatMap is used on the observable returned by retrofit service to create an observable that emits required data from response and finally you apply filter on each item so that only items which satisfy the condition will be finally emitted.
If there is an error in getting response from service, you can retry service call for certain number of times and with certain time gap between two calls using retrofit and rxjava.
Retrofit Rxjava Android Example
Below is an example which shows how to use Retrofit and Rxjava in android. On clicking a button, a retrofit service call is made in the background and view objects are updated with results.
This example also shows how to use and style card view with recycler view.
Add dependencies and permissions
In addition to above mentioned retrofit and rxjava dependencies, you need to add below dependencies for this example. And also add internet permission to manifest xml file.
Retrofit Interface
Activity
RecyclerView Adapter
RecyclerView Item Layout
About
Android app development tutorials and web app development tutorials with programming examples and code samples.
Источник
Retrofit. Query, Path, RxJava, логи
Продолжаем говорить про Retrofit. Посмотрим, что и как мы можем настроить в нем, чтобы достичь своих целей.
Основы работы с Retrofit вы можете посмотреть в прошлом посте. Я же вкратце напомню, что две основных части его конфигурирования — это интерфейс и билдер. В интерфейсе мы описываем, какие методы мы будем вызывать, а в билдере задаем базовый URL и можем добавлять различные дополнения и обработчики для запросов и ответов.
Сначала рассмотрим пару полезных трюков, которые мы можем провернуть в интерфейсе.
Разделение ссылки
Предположим, у нас есть API метод:
http://server/api/v1/products/list.
Он возвращает список товаров. Нам нужно разделить эту ссылку на базовый URL (для билдера) и имя метода (для интерфейса). Это можно сделать так:
http://server/api/v1/products/ — базовый URL
list — метод
Соответственно, интерфейс будет выглядеть так:
Но внезапно у нас в API добавляется еще один метод, который возвращает список заказов:
http://server/api/v1/orders/list
Если его разделить по той же схеме, то получится так:
http://server/api/v1/orders/ — базовый URL
list — метод
В интерфейс мы можем добавить метод orderList:
Но у нас в билдере использовался базовый URL:
http://server/api/v1/products/
А нам теперь нужно, чтобы для метода ordersList он был таким:
http://server/api/v1/orders/
Можно конечно разделить все это на два отдельных интерфейса и билдера. Но есть решение и для текущей конфигурации. Надо просто по-другому выделять базовый URL из ссылок.
Берем две ссылки:
http://server/api/v1/products/list
http://server/api/v1/orders/list.
У них можно выделить общий базовый URL:
http://server/api/v1/
Его и будем использовать в билдере. А каталоги products и orders пойдут в интерфейс.
Query
Рассмотрим пример запроса с параметрами. Предположим, что метод http://server/api/v1/products/list поддерживает некоторые параметры.
Например, мы можем указать id категории товара:
http://server/api/v1/products/list?category=100
Или тип сортировки:
http://server/api/v1/products/list?sort=desc
Или оба вместе:
http://server/api/v1/products/list?category=100&sort=desc
В интерфейсе это можно сделать так:
И это даже будет работать, но понятно, что решение совсем топорное. Если сортировку еще можно так оставить, то категорию уж точно хотелось бы вынести в параметры. Используем для этого аннотацию Query:
Сортировку мы так и оставили там же, где указываем имя API метода. А категорию мы вынесли в параметры метода productList и добавили к ней аннотацию Query. В аннотации мы указали под каким именем этот параметр должен появится в URL запроса.
Вызов этого метода в коде будет выглядеть так:
И в результате будет выполнен следующий запрос
http://server/api/v1/products/list?sort=desc&category=100
В одном методе можно указывать несколько Query параметров.
Иногда API может быть такого вида
Т.е. здесь id товара передается не параметром, а частью пути. В этом случае нам поможет аннотация Path.
Используем ее в методах интерфейса:
В строку с именем метода добавляем плэйсхолдер
При вызове, Retrofit возьмет значение productId и подставит его в строку запроса вместо
В одном методе можно указывать несколько Path параметров.
Логирование
Чтобы видеть, какие запросы уходят и какие ответы на них приходят, мы можем добавить к Retrofit логирование.
Для этого надо в build.gradle в секцию dependecies добавить зависимость:
Код конфигурации билдера теперь будет выглядеть так:
Сначала создаем HttpLoggingInterceptor. В нем настраиваем уровень логирования. Если у нас Debug билд, то выставляем максимальный уровень (BODY), иначе — ничего не логируем, чтобы не палить в логах релизные запросы.
HttpLoggingInterceptor мы не можем напрямую передать в Retrofit билдер. Поэтому сначала создаем OkHttpClient, ему передаем HttpLoggingInterceptor, и уже этот OkHttpClient используем в Retrofit билдере.
В результате, в логе по тегу OkHttp вы увидите все ваши запросы со всеми параметрами, заголовками и содержимым.
RxJava
Чтобы использовать в проекте RxJava, необходимо добавить зависимости:
А для Retrofit нужен RxJava-адаптер:
Вместо обертки Call мы используем Single из RxJava. Он вернет нам либо результат (onNext), либо ошибку (onError). А метод завершения (onCompleted) он вызывать не будет.
В билдере нам необходимо добавить RxJava2CallAdapterFactory:
Далее, создаем реализацию MessageApi и вызываем метод messages.
Метод messages вернет нам Single
>, на который мы подписываемся и настраиваем, чтобы запрос был выполнен в IO потоке, а результат вернулся в UI потоке.,
В случае использования RxJava, у нас уже нет объекта Response. И если сервер вернет какую-то ошибку, то мы получим ее в onError. Например, ошибка 404 будет выглядеть так:
onError retrofit2.adapter.rxjava2.HttpException: HTTP 404
Как получить чистый текст
Бывает необходимость получить от сервера данные в виде текста (plain text). Т.е. вам не надо, чтобы Retrofit распарсил текстовые данные в объекты. По каким-то причинам вы хотите получить String.
В интерфейсе указываем тип String
Получить строку нам поможет конвертер ScalarsConverterFactory. Чтобы использовать его, пропишите зависимость:
Используем ScalarsConverterFactory в билдере
Далее, все как обычно, получаем Call объект и асинхронно выполняем запрос:
Ответ придет в response.body()
В логах это будет выглядеть так:
Мы получили нераспарсенные json данные в виде текста.
Как сделать синхронный вызов
Если вы собираетесь выполнять запрос не в UI потоке, то его можно выполнить синхронно без всяких колбэков.
Это будет выглядеть так:
Этот код блокирует текущий поток. Ответ от сервера вы получите в Response объект. А если случится ошибка, то она придет в catch
Присоединяйтесь к нам в Telegram:
— в канале StartAndroid публикуются ссылки на новые статьи с сайта startandroid.ru и интересные материалы с хабра, medium.com и т.п.
— в чатах решаем возникающие вопросы и проблемы по различным темам: Android, Kotlin, RxJava, Dagger, Тестирование
— ну и если просто хочется поговорить с коллегами по разработке, то есть чат Флудильня
— новый чат Performance для обсуждения проблем производительности и для ваших пожеланий по содержанию курса по этой теме
Источник
Android RxJava Networking with Retrofit, Gson – Notes App
Retrofit is an awesome networking library because of it’s simplicity and ease of use. I have already written an article about Retrofit in plain android. In this article we are going to learn how use Retrofit with RxJava.
We’ll consider a simple use case of Notes App that consumes REST API and stores the notes on cloud storage.
DEMO
1. Prerequisite
Before start reading this article, I suggest you go through below tutorials and get familiar with the concepts.
- RxJava Understanding Observables to understand different types of Observables available in RxJava and the purpose of each.
- Android Working with Retrofit HTTP Library Implementation of Retrofit HTTP library without RxJava
- Android Working with Recycler View Basic list rendering using an Adapter.
- Android ButterKnife View binding / injection using ButterKnife library
2. App Design
I am keeping the app design to be very minimal. The app will have only one screen displaying the notes in a list manner. And there would be a FAB button and couple of Dialogs to create or edit the notes.
3. Notes REST API
To demonstrate this example, I have created a simple Notes REST API that simulates realtime api. You can perform CRUD operations (Create, Read, Update and Delete) on the api. Note that, as this is a demo app, you can create at max 15 notes only. I suggest you use this API for testing purpose only, don’t use it in your realtime apps.
Header Field | Value | Description |
---|---|---|
Authorization | 3d83ba21699XXX | Use the api_key received in /register call |
Content-Type | application/json | |
Endpoint | Method | Params |
/notes/user/register | POST | `device_id` – Unique identifier of the device |
/notes/all | GET | NONE |
/notes/new | POST | `note` – Note text |
/notes/ | PUT | `id` – Id of the note to be updated (Replace the with actual value in the URL) |
/notes/ | DELETE | `id` – Id of the note to be deleted |
4. Creating New Project
Now let’s begin by creating a new project in Android Studio. Once the project is created, we’ll do the basic setup like adding required dependencies, resource files and layouts those required for app design.
1. Create a new project in Android Studio from File ⇒ New Project and select Basic Activity from templates.
2. Add RecyclerView, ButterKnife and Retrofit dependencies to your app/build.gradle and Sync the project.
3. Add the below resources to respective colors.xml, strings.xml and dimens.xml.
4. Create an xml named array.xml under res ⇒ values. This file contains list of color codes those required to generate a random color dot before every note.
5. Open styles.xml and modify it as below. Here we are modifying the default theme and applying Light theme to our app.
6. Open AndroidManifest.xml and add INTERNET permission as we are going to make HTTP calls.
Now, as we have all the resources in place, let’s give a structure to our project. I am creating few packages to keep the project organised.
7. Create the packages named app, network, network/model, utils and view.
Below image gives you a heads-up about the final project structure and files we are aiming.
8. Under app package, create a class named Const.java. This file contains global static variables. I am declaring the REST API base URL here.
9. Utils package contains helper files required for this app. Under utils package, create a class named PrefUtils.java.
This class stores and retrieves the API Key that needs to be sent in every HTTP call as Authorization header field.
10. Create two more classes named MyDividerItemDecoration.java and RecyclerTouchListener.java. These two classes adds divider line and touch listener to RecyclerView.
4.1 Adding Retrofit Network Layer
Now we have reached to core part of the article i.e adding Retrofit network layer. We’ll start by adding few POJO classes necessary to serialize the JSON.
BaseResponse – As every response will have a error node, we define the error node in BaseResponse class and extend this class in other models.
User – User response once the device is registered. For now this model will have apiKey only.
Note – Defines the note object with id, note and timestamp fields.
11. Under network/model package, create a class named BaseResponse.java
12. Create another model User.java under network/model and extend the class from BaseResponse.
13. Create class Note.java under network/model and extend it from BaseResponse.
14. Under network package create a class named ApiClient.java and add below code. In this class we configure the Retrofit client by adding necessary configuration.
- The Authorization header field is added if the API Key is present in Shared Preferences. This header field is mandatory in every http call except /register call. Without proper API Key, all the calls will be denied.
- HttpLoggingInterceptor are added to print the Request / Response in LogCat for debugging purpose. You can notice the logged information in the LogCat of Android Studio.
15. Create a class named ApiService.java under network package. This class holds the interface methods of every endpoint by defining the endpoint, request and response Observable.
I hope you already had gone through RxJava Understanding Observables and aware of different types of Observables and their purpose.
- The Single Observable is used for the the endpoints register, notes/new and notes/all as single response will be emitted.
- Completable Observable is used for both update and delete endpoints as they won’t give any response but the status of the call. You can also notice PUT method is used to update and DELETE method is used to delete a note.
Using ApiClient and ApiService classes you can make a network call. For example, fetching all notes call can be made like below.
4.2 Adding Main Interface
At this stage we have everything in place. The only remaining part is building the main interface and integrate the Retrofit calls to display the data.
16. Create a layout file named note_list_row.xml. In this view file we define the design of the single row item of RecyclerView.
17. Under view package, Create a class named NotesAdapter.java. This adapter class renders the RecyclerView with defined layout and data.
- If you notice the app design, every note is prepending with coloured dot. To generate the dot with a random color, getRandomMaterialColor() method is used. It basically chooses a random color from array.xml
- formatDate() converts the received timestamp from the API to MMM d format. For example, the timestamp 2018-02-21 10:01:03 is converted to Feb 21.
18. Create another layout named note_dialog.xml. This layout will have an EditText to create or update a note.
19. Open the layout files of main activity i.e activity_main.xml and content_main.xml add AppBarLayout and RecyclerView.
20. Finally open MainActivity.java do the below modifications.
- registerUser() – Makes /register call to register the device. Every device is uniquely identified by randomUUID(), so the notes will be bound to a device.
- fetchAllNotes() – Fetches all the notes created from the device and displays them in RecyclerView. The API returns the notes in random order, so the map() operator is used to sort the notes in descending order by note id.
- createNote() – Creates new note and adds it to RecyclerView. The newly created note is added to 0 position and notifyItemInserted(0) is called to refresh the list.
- updateNote() – Updates existing note and notifies the adapter by calling notifyItemChanged()
- deleteNote() – Deletes existing note and notifies the adapter by calling notifyItemRemoved() method.
- showNoteDialog() – Opens a Dialog to Create or Update a note. This dialog will be opened by tapping on FAB.
- showActionsDialog() – Open a Dialog with Edit or Delete options. This dialog will be opened by long pressing Note row.
- CompositeDisposable – Disposes all the subscriptions in onDestroy() method
Run and test the app once. If you have followed article carefully, you can see the app running smoothly.
I hope this article explained Retrofit very well. If you have any queries, please comment below.
Источник