Exploring GraphQL on Android with Apollo

Exploring GraphQL on Android with Apollo

Presentation about GraphQL basics and how to integrate with GraphQL APIs on Android, using the Apollo Client.

Presented at Android DevConference 2017.

D4b7a3e2ed10f86e0b52498713ba2601?s=128

Ubiratan Soares

August 25, 2017
Tweet

Transcript

  1. EXPLORING GRAPHQL WITH APOLLO Ubiratan Soares Agosto / 2017

  2. None
  3. by

  4. None
  5. None
  6. IS NOT

  7. vs

  8. WE MUST TALK ABOUT REST

  9. None
  10. None
  11. 2000

  12. 2000

  13. 2017

  14. 2017

  15. REST WAS NOT DESIGNED WITH NOWADAYS APPLICATIONS, DEVICES AND USERS

    IN MIND …
  16. None
  17. Design Develop Measure API AS PRODUCT

  18. KNOW ISSUES FROM REST

  19. SCHEMA-LESS

  20. VERSIONING

  21. MULTIPLE ENDPOINTS TO SOLVE A SPECIFIC NEED FROM CLIENT

  22. ENDPOINT EXPOSES MORE DATA THAN CLIENT NEEDS PER HTTP REQUEST

  23. MAIN GOALS

  24. Single Endpoint “Goodbye" versioning headaches 1

  25. Well defined contract Client and server must respect a schema

    for effective data exchange 2
  26. No more overfetching GraphQL clients can fetch only the data

    they really need for a given purpose 3
  27. 4 No more underfetching GraphQL clients can retrieve all the

    data they need into a single HTTP call : no more chained and/or parallel HTTP requests
  28. CORE CONCEPTS

  29. None
  30. TYPE SYSTEM AND SCHEMA

  31. None
  32. None
  33. None
  34. None
  35. Field name != Type name

  36. QUERY (IP) LOCDATA city : city location : location LOCATION

    latitude : String longitude : String time_zone : String CITY geoname_id : String names : cityNames ACCEPTS RETURNS . . . . . . CITYNAMES de : String en : String ru : String . . .
  37. QUERIES AND MUTATIONS

  38. { getLocation(ip: “172.59.226.170") { country { names { en }

    geoname_id iso_code } location { latitude longitude } } } Operation Root Query parameter Data that actually matters
  39. { getLocation(ip: “172.59.226.170") { country { names { en }

    geoname_id iso_code } location { latitude longitude } } } "For the available data, return the English name for the country"
  40. { getLocation(ip: “172.59.226.170") { country { names { en }

    geoname_id iso_code } location { latitude longitude } } } "For the available data, return the latitude and the longitude from the geolocation info"
  41. { "data": { "getLocation": { "country": { "names": { "en":

    "Brazil" }, "geoname_id": "3469034", "iso_code": "BR" }, "location": { "latitude": "-23.5733", "longitude": "-46.6417" } } } } QUERY
  42. None
  43. None
  44. MORE ABOUT OPERATIONS • Data payload will mirror the type

    hierarchy defined on schema • All data types for queries/mutations must be defined on schema • Operation can accept parameters and/or variables • We can form better, readable blocks for operations using aliases and fragments • Etc
  45. CLIENT INTENT REST + HTTP GraphQL + HTTP GraphQL Operation

    READ RESOURCE GET POST QUERY CREATE RESOURCE POST POST MUTATION UPDATE RESOURCE PUT POST MUTATION REMOVE RESOURCE DELETE POST MUTATION
  46. HOW TO USE ON ANDROID ?

  47. None
  48. None
  49. APOLLO + ANDROID • Full-featured tooling + library, inspired by

    Retrofit • Custom OkHttpClient support • Code generation for queries / mutations : request models and payloads • Cache-ready client, including L0, L1 e L2 support • RxJava support • Etc
  50. None
  51. PREPARE YOUR QUERY OR MUTATION

  52. query LocationQuery ($ip: String!) { getLocation(ip: $ip) { country {

    names { en } geoname_id iso_code } location { latitude longitude } } } Generated class member To-be-generated class name Operation Type
  53. query LocationQuery($ip: String!) { getLocation(ip: $ip) { country { names

    { en } geoname_id iso_code } location { latitude longitude } } } queryname.graphql
  54. RETRIEVE THE ACTUAL SCHEMA

  55. None
  56. > brew install npm

  57. > brew install npm > npm install -g apollo-codegen

  58. > apollo-codegen download-schema \ https://api.graphloc.com/graphql \ --output schema.json > brew

    install npm > npm install -g apollo-codegen
  59. PROJECT INTEGRATION

  60. APPLY PLUGIN AND DEPENDENCIES

  61. DEFINE YOUR WORK DIRECTORY

  62. Define the package for generated classes Convention DO NOT forget

    to put schema here
  63. class GraphQLAccess { private val apolloClient = ApolloClient .builder() .serverUrl("https://api.graphloc.com/graphql")

    .build() } // continue ... }
  64. fun fetchGeolocation(): Observable<GeolocationInformation> { val ipAddress = "8.8.8.8" val locationQuery

    = LocationQuery.builder() .ip(ipAddress) .build() val call = apolloClient.query<Data, Data, Variables>(locationQuery) return Rx2Apollo .from<Data>(call) .map { data -> toGeolocationInfo(data, ipAddress) } }
  65. fun fetchGeolocation(): Observable<GeolocationInformation> { val ipAddress = "8.8.8.8" val locationQuery

    = LocationQuery.builder() .ip(ipAddress) .build() val call = apolloClient.query<Data, Data, Variables>(locationQuery) return Rx2Apollo .from<Data>(call) .map { data -> toGeolocationInfo(data, ipAddress) } }
  66. fun fetchGeolocation(): Observable<GeolocationInformation> { val ipAddress = "8.8.8.8" val locationQuery

    = LocationQuery.builder() .ip(ipAddress) .build() val call = apolloClient.query<Data, Data, Variables>(locationQuery) return Rx2Apollo .from<Data>(call) .map { data -> toGeolocationInfo(data, ipAddress) } }
  67. fun fetchGeolocation(): Observable<GeolocationInformation> { val ipAddress = "8.8.8.8" val locationQuery

    = LocationQuery.builder() .ip(ipAddress) .build() val call = apolloClient.query<Data, Data, Variables>(locationQuery) return Rx2Apollo .from<Data>(call) .map { data -> toGeolocationInfo(data, ipAddress) } }
  68. private fun toGeolocationInfo( dataResponse: Response<Data>, ipAddress: String): GeolocationInformation { val

    data = dataResponse.data()?.getLocation val location = data?.location return GeolocationInformation( ip = ipAddress, countryName = data?.country?.names?.en, cityName = data?.city?.names?.en, latitude = location?.latitude, longitutde = location?.longitude, timezone = location?.time_zone ) }
  69. private fun toGeolocationInfo( dataResponse: Response<Data>, ipAddress: String): GeolocationInformation { val

    data = dataResponse.data()?.getLocation val location = data?.location return GeolocationInformation( ip = ipAddress, countryName = data?.country?.names?.en, cityName = data?.city?.names?.en, latitude = location?.latitude, longitutde = location?.longitude, timezone = location?.time_zone ) } Generated by Apollo
  70. DONE

  71. JUST ADD MORE QUERIES / MUTATIONS AND BE HAPPY !!!

  72. FINAL REMARKS

  73. FINAL REMARKS • GraphQL is just a spec

  74. FINAL REMARKS • GraphQL is just a spec • GraphQL

    aims to solve some of well know issues from REST
  75. FINAL REMARKS • GraphQL is just a spec • GraphQL

    aims to solve some of well know issues from REST • GraphQL is mobile friendly, but it brings its own set of challenges (for free, rs)
  76. FINAL REMARKS • GraphQL is just a spec • GraphQL

    aims to solve some of well know issues from REST • GraphQL is mobile friendly, but it brings its own set of challenges (for free, rs) • Apollo is an OSS effort for easy integration of GraphQL clients, and it has a full-featured Android native API
  77. REFERENCES Oficial GraphQL Website http://graphql.org How to GraphQL https://www.howtographql.com Github

    Training on GraphQL https://services.github.com/on-demand/graphql Apollo Client for Android - Documentation http://dev.apollodata.com/android
  78. https://speakerdeck.com/ubiratansoares

  79. UBIRATAN SOARES Computer Scientist by ICMC/USP Software Engineer, curious guy

    Google Developer Expert for Android Teacher, speaker, etc, etc
  80. THANK YOU @ubiratanfsoares ubiratansoares.github.io https://br.linkedin.com/in/ubiratanfsoares