Extending Retrofit for fun and profit

Matthew Clarke
Matthew ClarkeSenior Software Developer at Spark New Zealand
Extending Retrofit for fun
and profit
Matt Clarke - 4 July 2017, Orion Health Akl
Retrofit (v2.1.0) recap
// Retrofit turns your HTTP API into a Java (or Kotlin)
interface
public interface GitHubService {
@GET("users/{user}/repos")
Call<List<Repo>> listRepos(@Path("user") String user);
}
Define a light-weight interface that matches the REST endpoint you want to talk to
Retrofit retrofit = new Retrofit.Builder()
.baseUrl("https://api.github.com/")
.build();
GitHubService service =
retrofit.create(GitHubService.class);
Now you can use a Retrofit instance to generate a working version of your interface
to make requests with
Call<List<Repo>> repos = service.listRepos("octocat");
// synchronous/blocking request
Response<List<Repo>> response = repos.execute();
// do stuff with response...
To actually make a request, you just call the method you defined in your interface.
You’ll get back a Call object.
You can use this to make a sync request like this...
Call<List<Repo>> repos = service.listRepos("octocat");
// asynchronous request
repos.enqueue(new Callback<List<Repo>>() {
@Override
public void onResponse(Call<List<Repo>> call,
Response<List<Repo>> response) {
// do stuff with response...
}
@Override
public void onFailure(Call<List<Repo>> call, Throwable t) {
// uh oh!
}
});
Or you can use Call objects to make an asynchronous requests by calling enqueue
and passing a callback
Call<List<Repo>> repos = service.listRepos("octocat");
// asynchronous request
repos.enqueue(new Callback<List<Repo>>() {
@Override
public void onResponse(Call<List<Repo>> call,
Response<List<Repo>> response) {
// do stuff with response...
}
@Override
public void onFailure(Call<List<Repo>> call, Throwable t) {
// uh oh!
}
});
You might notice there are some similarities here with a library we’re all familiar with.
This Callback object looks a lot like an RxJava Observer or Subscriber.
Wouldn’t it be cool if the service returned an Observable instead of a Call? Then we
could go nuts with operators, subscribing on a different thread, etc.
Retrofit retrofit = new Retrofit.Builder()
.baseUrl("https://api.github.com/")
.build();
GitHubService service = retrofit.create(GitHubService.class);
Retrofit retrofit = new Retrofit.Builder()
.baseUrl("https://api.github.com/")
.addCallAdapterFactory(
RxJavaCallAdapterFactory.create()
)
.build();
GitHubService service = retrofit.create(GitHubService.class);
// Retrofit turns your HTTP API into a Java (or Kotlin)
interface
public interface GitHubService {
@GET("users/{user}/repos")
Call<List<Repo>> listRepos(@Path("user") String user);
}
// Retrofit turns your HTTP API into a Java (or Kotlin)
interface
public interface GitHubService {
@GET("users/{user}/repos")
Observable<List<Repo>> listRepos(@Path("user") String user);
}
Q: How does this magic work?
A: Call Adapters
WTF is a Call Adapter?
● Knows how to convert Call<R> to some other
type T
● E.g. the RxJavaCallAdapter can convert a
Call<Repo> into Observable<Repo>
WTF is a Call Adapter?
public interface CallAdapter<R, T> {
T adapt(Call<R> call);
Type responseType();
}
WTF is a Call Adapter?
● You also need to create a
CallAdapter.Factory to give to the
Retrofit.Builder
● Factories are given the chance to create
CallAdapters for a given return type in the
Service interface (e.g. Observable)
abstract class Factory {
/**
* Returns a call adapter for interface methods that
* return returnType, or null if it cannot be handled by
* this factory.
*/
public abstract @Nullable CallAdapter<?, ?> get(Type returnType,
Annotation[] annotations,
Retrofit retrofit);
// ..
}
Concrete example - Engage Mobile
Problem: Network Error handling
● The RxJavaCallAdapter just forwards low-level network
Exceptions via onError()
Problem: Network Error handling
val repoObservable = service.listRepos("octocat")
repoObservable.subscribe(object : Observer<List<Repo>> {
override fun onNext(repos: List<Repo>) {
// show repos in UI...
}
override fun onCompleted() {}
override fun onError(e: Throwable) {
when (e) {
is SocketTimeoutException -> showTimeoutError()
is ConnectException -> showNoConnectionToServerError()
is UnknownHostException -> showNoNetworkConnectionError()
is HttpException -> makeSenseOfHttpResponseCode(e)
}
}
})
You need to handle all of the
possible network errors
somewhere in order to do the
right thing in the UI.
Don’t want to have a copy of this
`when` statement everywhere
there’s a network call.
Also, these errors are low-level
and depend on the HTTP client
you’re using: if you change
HTTP libraries you don’t want all
of your UI code to break - they’re
separate concerns.
Network Error Handling
sealed class NetworkError(cause: Throwable?) :
Throwable(cause) {
class NetworkUnreachableError(cause: Throwable? = null) :
NetworkError(cause)
class ServerUnreachableError(cause: Throwable? = null) :
NetworkError(cause)
class GenericNetworkError(cause: Throwable? = null) :
NetworkError(cause)
} Solution: abstract away low-level HTTP client errors by defining your own
higher-level network error types
Network Error Handling
fun map(input: Throwable): Throwable {
if (!networkAccessAvailable())
return NetworkError.NetworkUnreachableError(input)
return when (input) {
is SocketTimeoutException ->
NetworkError.ServerUnreachableError(cause = input)
is ConnectException ->
NetworkError.ServerUnreachableError(cause = input)
is UnknownHostException ->
NetworkError.NetworkUnreachableError(cause = input)
is HttpException ->
mapHttpException(input)
else -> input
}
}
...Then you can extract out a common network error mapper,
and apply this to the reactive stream with the
onErrorResumeNext operator
Network Error Handling
repoObservable
.onErrorResumeNext { e ->
Observable.error(mapNetworkError(e))
}
.subscribe(object : Observer<List<Repo>> {
// ..
})
The problem with this is you still need to remember to apply this
mapper to all reactive streams that contain a network request.
Having to remember = a red flag. Better to structure the system
such that it does the right thing by default (remembers for you)
Live code demo
1 of 24

Recommended

Retrofit by
RetrofitRetrofit
RetrofitAmin Cheloh
1.6K views13 slides
Android Libs - Retrofit by
Android Libs - RetrofitAndroid Libs - Retrofit
Android Libs - RetrofitDaniel Costa Gimenes
2.7K views33 slides
Retrofit 2 - O que devemos saber by
Retrofit 2 - O que devemos saberRetrofit 2 - O que devemos saber
Retrofit 2 - O que devemos saberBruno Vieira
409 views32 slides
Retrofit by
RetrofitRetrofit
Retrofitbresiu
1.9K views27 slides
Infinum Android Talks #16 - Retrofit 2 by Kristijan Jurkovic by
Infinum Android Talks #16 - Retrofit 2 by Kristijan JurkovicInfinum Android Talks #16 - Retrofit 2 by Kristijan Jurkovic
Infinum Android Talks #16 - Retrofit 2 by Kristijan JurkovicInfinum
467 views12 slides
Tamir Dresher - Async Streams in C# by
Tamir Dresher - Async Streams in C#Tamir Dresher - Async Streams in C#
Tamir Dresher - Async Streams in C#Tamir Dresher
105 views9 slides

More Related Content

What's hot

HTTP Whiteboard - OSGI Compendium 6.0 - How web apps should have been! - R Auge by
HTTP Whiteboard - OSGI Compendium 6.0 - How web apps should have been! - R AugeHTTP Whiteboard - OSGI Compendium 6.0 - How web apps should have been! - R Auge
HTTP Whiteboard - OSGI Compendium 6.0 - How web apps should have been! - R Augemfrancis
1.9K views16 slides
Whats New in the Http Service Specification - Felix Meschberger by
Whats New in the Http Service Specification - Felix MeschbergerWhats New in the Http Service Specification - Felix Meschberger
Whats New in the Http Service Specification - Felix Meschbergermfrancis
748 views21 slides
Servlet life cycle by
Servlet life cycleServlet life cycle
Servlet life cycleVenkateswara Rao N
771 views35 slides
MongoDB World 2016: Implementing Async Networking in MongoDB 3.2 by
MongoDB World 2016: Implementing Async Networking in MongoDB 3.2MongoDB World 2016: Implementing Async Networking in MongoDB 3.2
MongoDB World 2016: Implementing Async Networking in MongoDB 3.2MongoDB
811 views50 slides
Request dispatching in servlet by
Request dispatching in servletRequest dispatching in servlet
Request dispatching in servletvikram singh
4.4K views27 slides
Why async matters by
Why async mattersWhy async matters
Why async matterstimbc
878 views54 slides

What's hot(20)

HTTP Whiteboard - OSGI Compendium 6.0 - How web apps should have been! - R Auge by mfrancis
HTTP Whiteboard - OSGI Compendium 6.0 - How web apps should have been! - R AugeHTTP Whiteboard - OSGI Compendium 6.0 - How web apps should have been! - R Auge
HTTP Whiteboard - OSGI Compendium 6.0 - How web apps should have been! - R Auge
mfrancis1.9K views
Whats New in the Http Service Specification - Felix Meschberger by mfrancis
Whats New in the Http Service Specification - Felix MeschbergerWhats New in the Http Service Specification - Felix Meschberger
Whats New in the Http Service Specification - Felix Meschberger
mfrancis748 views
MongoDB World 2016: Implementing Async Networking in MongoDB 3.2 by MongoDB
MongoDB World 2016: Implementing Async Networking in MongoDB 3.2MongoDB World 2016: Implementing Async Networking in MongoDB 3.2
MongoDB World 2016: Implementing Async Networking in MongoDB 3.2
MongoDB811 views
Request dispatching in servlet by vikram singh
Request dispatching in servletRequest dispatching in servlet
Request dispatching in servlet
vikram singh4.4K views
Why async matters by timbc
Why async mattersWhy async matters
Why async matters
timbc878 views
Kotlin 1.2: Sharing code between platforms by Kirill Rozov
Kotlin 1.2: Sharing code between platformsKotlin 1.2: Sharing code between platforms
Kotlin 1.2: Sharing code between platforms
Kirill Rozov551 views
Wrapping java in awesomeness aka condensator by Flowa Oy
Wrapping java in awesomeness aka condensatorWrapping java in awesomeness aka condensator
Wrapping java in awesomeness aka condensator
Flowa Oy1.2K views
Servlet and servlet life cycle by Dhruvin Nakrani
Servlet and servlet life cycleServlet and servlet life cycle
Servlet and servlet life cycle
Dhruvin Nakrani3.6K views
Background Jobs with Resque by homanj
Background Jobs with ResqueBackground Jobs with Resque
Background Jobs with Resque
homanj6.6K views
Contract-driven development with OpenAPI 3 and Vert.x | DevNation Tech Talk by Red Hat Developers
Contract-driven development with OpenAPI 3 and Vert.x | DevNation Tech TalkContract-driven development with OpenAPI 3 and Vert.x | DevNation Tech Talk
Contract-driven development with OpenAPI 3 and Vert.x | DevNation Tech Talk
Red Hat Developers3.8K views
Servlet api &amp; servlet http package by renukarenuka9
Servlet api &amp; servlet http packageServlet api &amp; servlet http package
Servlet api &amp; servlet http package
renukarenuka9152 views
Generating cross platform .NET based azure IoTdevice by Alon Fliess
Generating cross platform .NET based azure IoTdeviceGenerating cross platform .NET based azure IoTdevice
Generating cross platform .NET based azure IoTdevice
Alon Fliess144 views
Asynchronous handlers in asp.net by Abhishek Sur
Asynchronous handlers in asp.netAsynchronous handlers in asp.net
Asynchronous handlers in asp.net
Abhishek Sur1.9K views
Making the Most of Your Gradle Build by Andres Almiray
Making the Most of Your Gradle BuildMaking the Most of Your Gradle Build
Making the Most of Your Gradle Build
Andres Almiray1.5K views

Similar to Extending Retrofit for fun and profit

Java Libraries You Can’t Afford to Miss by
Java Libraries You Can’t Afford to Miss Java Libraries You Can’t Afford to Miss
Java Libraries You Can’t Afford to Miss Andres Almiray
3K views64 slides
Arquitecturas de microservicios - Medianet Software by
Arquitecturas de microservicios   -  Medianet SoftwareArquitecturas de microservicios   -  Medianet Software
Arquitecturas de microservicios - Medianet SoftwareErnesto Hernández Rodríguez
1.8K views54 slides
1 java servlets and jsp by
1   java servlets and jsp1   java servlets and jsp
1 java servlets and jspAnkit Minocha
17.8K views368 slides
Java servlets by
Java servletsJava servlets
Java servletsyuvarani p
129 views51 slides
Retrofit library for android by
Retrofit library for androidRetrofit library for android
Retrofit library for androidInnovationM
89 views4 slides
Retrofit Library In Android by
Retrofit Library In AndroidRetrofit Library In Android
Retrofit Library In AndroidInnovationM
514 views4 slides

Similar to Extending Retrofit for fun and profit(20)

Java Libraries You Can’t Afford to Miss by Andres Almiray
Java Libraries You Can’t Afford to Miss Java Libraries You Can’t Afford to Miss
Java Libraries You Can’t Afford to Miss
Andres Almiray3K views
1 java servlets and jsp by Ankit Minocha
1   java servlets and jsp1   java servlets and jsp
1 java servlets and jsp
Ankit Minocha17.8K views
Java servlets by yuvarani p
Java servletsJava servlets
Java servlets
yuvarani p129 views
Retrofit library for android by InnovationM
Retrofit library for androidRetrofit library for android
Retrofit library for android
InnovationM89 views
Retrofit Library In Android by InnovationM
Retrofit Library In AndroidRetrofit Library In Android
Retrofit Library In Android
InnovationM514 views
Native REST Web Services with Oracle 11g by Marcelo Ochoa
Native REST Web Services with Oracle 11gNative REST Web Services with Oracle 11g
Native REST Web Services with Oracle 11g
Marcelo Ochoa3.4K views
Clojure and the Web by nickmbailey
Clojure and the WebClojure and the Web
Clojure and the Web
nickmbailey1.9K views
May 2010 - RestEasy by JBug Italy
May 2010 - RestEasyMay 2010 - RestEasy
May 2010 - RestEasy
JBug Italy1.3K views
Implement Service Broker with Spring Boot #cf_tokyo by Toshiaki Maki
Implement Service Broker with Spring Boot #cf_tokyoImplement Service Broker with Spring Boot #cf_tokyo
Implement Service Broker with Spring Boot #cf_tokyo
Toshiaki Maki3.1K views
Servlet 01 by Bharat777
Servlet 01Servlet 01
Servlet 01
Bharat777772 views
GDG Devfest 2019 - Build go kit microservices at kubernetes with ease by KAI CHU CHUNG
GDG Devfest 2019 - Build go kit microservices at kubernetes with easeGDG Devfest 2019 - Build go kit microservices at kubernetes with ease
GDG Devfest 2019 - Build go kit microservices at kubernetes with ease
KAI CHU CHUNG926 views
Networked APIs with swift by Tim Burks
Networked APIs with swiftNetworked APIs with swift
Networked APIs with swift
Tim Burks669 views
Java Web Programming [2/9] : Servlet Basic by IMC Institute
Java Web Programming [2/9] : Servlet BasicJava Web Programming [2/9] : Servlet Basic
Java Web Programming [2/9] : Servlet Basic
IMC Institute1.7K views
Networking and Data Access with Eqela by jobandesther
Networking and Data Access with EqelaNetworking and Data Access with Eqela
Networking and Data Access with Eqela
jobandesther1.7K views

Recently uploaded

What is API by
What is APIWhat is API
What is APIartembondar5
16 views15 slides
Transport Management System - Shipment & Container Tracking by
Transport Management System - Shipment & Container TrackingTransport Management System - Shipment & Container Tracking
Transport Management System - Shipment & Container TrackingFreightoscope
6 views3 slides
Automated Testing of Microsoft Power BI Reports by
Automated Testing of Microsoft Power BI ReportsAutomated Testing of Microsoft Power BI Reports
Automated Testing of Microsoft Power BI ReportsRTTS
13 views20 slides
JioEngage_Presentation.pptx by
JioEngage_Presentation.pptxJioEngage_Presentation.pptx
JioEngage_Presentation.pptxadmin125455
9 views4 slides
Mobile App Development Company by
Mobile App Development CompanyMobile App Development Company
Mobile App Development CompanyRichestsoft
6 views6 slides
Ports-and-Adapters Architecture for Embedded HMI by
Ports-and-Adapters Architecture for Embedded HMIPorts-and-Adapters Architecture for Embedded HMI
Ports-and-Adapters Architecture for Embedded HMIBurkhard Stubert
37 views19 slides

Recently uploaded(20)

Transport Management System - Shipment & Container Tracking by Freightoscope
Transport Management System - Shipment & Container TrackingTransport Management System - Shipment & Container Tracking
Transport Management System - Shipment & Container Tracking
Freightoscope 6 views
Automated Testing of Microsoft Power BI Reports by RTTS
Automated Testing of Microsoft Power BI ReportsAutomated Testing of Microsoft Power BI Reports
Automated Testing of Microsoft Power BI Reports
RTTS13 views
JioEngage_Presentation.pptx by admin125455
JioEngage_Presentation.pptxJioEngage_Presentation.pptx
JioEngage_Presentation.pptx
admin1254559 views
Mobile App Development Company by Richestsoft
Mobile App Development CompanyMobile App Development Company
Mobile App Development Company
Richestsoft 6 views
Ports-and-Adapters Architecture for Embedded HMI by Burkhard Stubert
Ports-and-Adapters Architecture for Embedded HMIPorts-and-Adapters Architecture for Embedded HMI
Ports-and-Adapters Architecture for Embedded HMI
Burkhard Stubert37 views
Unlocking the Power of AI in Product Management - A Comprehensive Guide for P... by NimaTorabi2
Unlocking the Power of AI in Product Management - A Comprehensive Guide for P...Unlocking the Power of AI in Product Management - A Comprehensive Guide for P...
Unlocking the Power of AI in Product Management - A Comprehensive Guide for P...
NimaTorabi219 views
Electronic AWB - Electronic Air Waybill by Freightoscope
Electronic AWB - Electronic Air Waybill Electronic AWB - Electronic Air Waybill
Electronic AWB - Electronic Air Waybill
Freightoscope 7 views
aATP - New Correlation Confirmation Feature.pptx by EsatEsenek1
aATP - New Correlation Confirmation Feature.pptxaATP - New Correlation Confirmation Feature.pptx
aATP - New Correlation Confirmation Feature.pptx
EsatEsenek1225 views
Advanced API Mocking Techniques Using Wiremock by Dimpy Adhikary
Advanced API Mocking Techniques Using WiremockAdvanced API Mocking Techniques Using Wiremock
Advanced API Mocking Techniques Using Wiremock
Dimpy Adhikary5 views
How To Make Your Plans Suck Less — Maarten Dalmijn at the 57th Hands-on Agile... by Stefan Wolpers
How To Make Your Plans Suck Less — Maarten Dalmijn at the 57th Hands-on Agile...How To Make Your Plans Suck Less — Maarten Dalmijn at the 57th Hands-on Agile...
How To Make Your Plans Suck Less — Maarten Dalmijn at the 57th Hands-on Agile...
Stefan Wolpers49 views
tecnologia18.docx by nosi6702
tecnologia18.docxtecnologia18.docx
tecnologia18.docx
nosi67026 views
Streamlining Your Business Operations with Enterprise Application Integration... by Flexsin
Streamlining Your Business Operations with Enterprise Application Integration...Streamlining Your Business Operations with Enterprise Application Integration...
Streamlining Your Business Operations with Enterprise Application Integration...
Flexsin 5 views
Understanding HTML terminology by artembondar5
Understanding HTML terminologyUnderstanding HTML terminology
Understanding HTML terminology
artembondar59 views

Extending Retrofit for fun and profit

  • 1. Extending Retrofit for fun and profit Matt Clarke - 4 July 2017, Orion Health Akl
  • 3. // Retrofit turns your HTTP API into a Java (or Kotlin) interface public interface GitHubService { @GET("users/{user}/repos") Call<List<Repo>> listRepos(@Path("user") String user); } Define a light-weight interface that matches the REST endpoint you want to talk to
  • 4. Retrofit retrofit = new Retrofit.Builder() .baseUrl("https://api.github.com/") .build(); GitHubService service = retrofit.create(GitHubService.class); Now you can use a Retrofit instance to generate a working version of your interface to make requests with
  • 5. Call<List<Repo>> repos = service.listRepos("octocat"); // synchronous/blocking request Response<List<Repo>> response = repos.execute(); // do stuff with response... To actually make a request, you just call the method you defined in your interface. You’ll get back a Call object. You can use this to make a sync request like this...
  • 6. Call<List<Repo>> repos = service.listRepos("octocat"); // asynchronous request repos.enqueue(new Callback<List<Repo>>() { @Override public void onResponse(Call<List<Repo>> call, Response<List<Repo>> response) { // do stuff with response... } @Override public void onFailure(Call<List<Repo>> call, Throwable t) { // uh oh! } }); Or you can use Call objects to make an asynchronous requests by calling enqueue and passing a callback
  • 7. Call<List<Repo>> repos = service.listRepos("octocat"); // asynchronous request repos.enqueue(new Callback<List<Repo>>() { @Override public void onResponse(Call<List<Repo>> call, Response<List<Repo>> response) { // do stuff with response... } @Override public void onFailure(Call<List<Repo>> call, Throwable t) { // uh oh! } }); You might notice there are some similarities here with a library we’re all familiar with. This Callback object looks a lot like an RxJava Observer or Subscriber. Wouldn’t it be cool if the service returned an Observable instead of a Call? Then we could go nuts with operators, subscribing on a different thread, etc.
  • 8. Retrofit retrofit = new Retrofit.Builder() .baseUrl("https://api.github.com/") .build(); GitHubService service = retrofit.create(GitHubService.class);
  • 9. Retrofit retrofit = new Retrofit.Builder() .baseUrl("https://api.github.com/") .addCallAdapterFactory( RxJavaCallAdapterFactory.create() ) .build(); GitHubService service = retrofit.create(GitHubService.class);
  • 10. // Retrofit turns your HTTP API into a Java (or Kotlin) interface public interface GitHubService { @GET("users/{user}/repos") Call<List<Repo>> listRepos(@Path("user") String user); }
  • 11. // Retrofit turns your HTTP API into a Java (or Kotlin) interface public interface GitHubService { @GET("users/{user}/repos") Observable<List<Repo>> listRepos(@Path("user") String user); }
  • 12. Q: How does this magic work?
  • 14. WTF is a Call Adapter? ● Knows how to convert Call<R> to some other type T ● E.g. the RxJavaCallAdapter can convert a Call<Repo> into Observable<Repo>
  • 15. WTF is a Call Adapter? public interface CallAdapter<R, T> { T adapt(Call<R> call); Type responseType(); }
  • 16. WTF is a Call Adapter? ● You also need to create a CallAdapter.Factory to give to the Retrofit.Builder ● Factories are given the chance to create CallAdapters for a given return type in the Service interface (e.g. Observable)
  • 17. abstract class Factory { /** * Returns a call adapter for interface methods that * return returnType, or null if it cannot be handled by * this factory. */ public abstract @Nullable CallAdapter<?, ?> get(Type returnType, Annotation[] annotations, Retrofit retrofit); // .. }
  • 18. Concrete example - Engage Mobile
  • 19. Problem: Network Error handling ● The RxJavaCallAdapter just forwards low-level network Exceptions via onError()
  • 20. Problem: Network Error handling val repoObservable = service.listRepos("octocat") repoObservable.subscribe(object : Observer<List<Repo>> { override fun onNext(repos: List<Repo>) { // show repos in UI... } override fun onCompleted() {} override fun onError(e: Throwable) { when (e) { is SocketTimeoutException -> showTimeoutError() is ConnectException -> showNoConnectionToServerError() is UnknownHostException -> showNoNetworkConnectionError() is HttpException -> makeSenseOfHttpResponseCode(e) } } }) You need to handle all of the possible network errors somewhere in order to do the right thing in the UI. Don’t want to have a copy of this `when` statement everywhere there’s a network call. Also, these errors are low-level and depend on the HTTP client you’re using: if you change HTTP libraries you don’t want all of your UI code to break - they’re separate concerns.
  • 21. Network Error Handling sealed class NetworkError(cause: Throwable?) : Throwable(cause) { class NetworkUnreachableError(cause: Throwable? = null) : NetworkError(cause) class ServerUnreachableError(cause: Throwable? = null) : NetworkError(cause) class GenericNetworkError(cause: Throwable? = null) : NetworkError(cause) } Solution: abstract away low-level HTTP client errors by defining your own higher-level network error types
  • 22. Network Error Handling fun map(input: Throwable): Throwable { if (!networkAccessAvailable()) return NetworkError.NetworkUnreachableError(input) return when (input) { is SocketTimeoutException -> NetworkError.ServerUnreachableError(cause = input) is ConnectException -> NetworkError.ServerUnreachableError(cause = input) is UnknownHostException -> NetworkError.NetworkUnreachableError(cause = input) is HttpException -> mapHttpException(input) else -> input } } ...Then you can extract out a common network error mapper, and apply this to the reactive stream with the onErrorResumeNext operator
  • 23. Network Error Handling repoObservable .onErrorResumeNext { e -> Observable.error(mapNetworkError(e)) } .subscribe(object : Observer<List<Repo>> { // .. }) The problem with this is you still need to remember to apply this mapper to all reactive streams that contain a network request. Having to remember = a red flag. Better to structure the system such that it does the right thing by default (remembers for you)