$30 off During Our Annual Pro Sale. View Details »

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.

Ubiratan Soares
PRO

August 25, 2017
Tweet

More Decks by Ubiratan Soares

Other Decks in Programming

Transcript

  1. EXPLORING
    GRAPHQL WITH
    APOLLO
    Ubiratan Soares
    Agosto / 2017

    View Slide

  2. View Slide

  3. by

    View Slide

  4. View Slide

  5. View Slide

  6. IS NOT

    View Slide

  7. vs

    View Slide

  8. WE MUST TALK ABOUT
    REST

    View Slide

  9. View Slide

  10. View Slide

  11. 2000

    View Slide

  12. 2000

    View Slide

  13. 2017

    View Slide

  14. 2017

    View Slide

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

    View Slide

  16. View Slide

  17. Design
    Develop
    Measure
    API
    AS PRODUCT

    View Slide

  18. KNOW ISSUES FROM
    REST

    View Slide

  19. SCHEMA-LESS

    View Slide

  20. VERSIONING

    View Slide

  21. MULTIPLE ENDPOINTS
    TO SOLVE A SPECIFIC
    NEED FROM CLIENT

    View Slide

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

    View Slide

  23. MAIN
    GOALS

    View Slide

  24. Single Endpoint
    “Goodbye" versioning
    headaches
    1

    View Slide

  25. Well defined contract
    Client and server must respect
    a schema for effective data
    exchange
    2

    View Slide

  26. No more overfetching
    GraphQL clients can fetch only
    the data they really need for a
    given purpose
    3

    View Slide

  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

    View Slide

  28. CORE
    CONCEPTS

    View Slide

  29. View Slide

  30. TYPE SYSTEM
    AND SCHEMA

    View Slide

  31. View Slide

  32. View Slide

  33. View Slide

  34. View Slide

  35. Field name != Type name

    View Slide

  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
    .
    .
    .

    View Slide

  37. QUERIES AND
    MUTATIONS

    View Slide

  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

    View Slide

  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"

    View Slide

  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"

    View Slide

  41. {
    "data": {
    "getLocation": {
    "country": {
    "names": {
    "en": "Brazil"
    },
    "geoname_id": "3469034",
    "iso_code": "BR"
    },
    "location": {
    "latitude": "-23.5733",
    "longitude": "-46.6417"
    }
    }
    }
    }
    QUERY

    View Slide

  42. View Slide

  43. View Slide

  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

    View Slide

  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

    View Slide

  46. HOW TO USE
    ON ANDROID ?

    View Slide

  47. View Slide

  48. View Slide

  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

    View Slide

  50. View Slide

  51. PREPARE YOUR
    QUERY OR
    MUTATION

    View Slide

  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

    View Slide

  53. query LocationQuery($ip: String!) {
    getLocation(ip: $ip) {
    country {
    names {
    en
    }
    geoname_id
    iso_code
    }
    location {
    latitude
    longitude
    }
    }
    }
    queryname.graphql

    View Slide

  54. RETRIEVE THE
    ACTUAL SCHEMA

    View Slide

  55. View Slide

  56. > brew install npm

    View Slide

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

    View Slide

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

    View Slide

  59. PROJECT
    INTEGRATION

    View Slide

  60. APPLY PLUGIN AND
    DEPENDENCIES

    View Slide

  61. DEFINE YOUR
    WORK DIRECTORY

    View Slide

  62. Define the package for generated classes
    Convention
    DO NOT forget to put schema here

    View Slide

  63. class GraphQLAccess {
    private val apolloClient = ApolloClient
    .builder()
    .serverUrl("https://api.graphloc.com/graphql")
    .build()
    }
    // continue ...
    }

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

  68. private fun toGeolocationInfo(
    dataResponse: Response,
    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
    )
    }

    View Slide

  69. private fun toGeolocationInfo(
    dataResponse: Response,
    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

    View Slide

  70. DONE

    View Slide

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

    View Slide

  72. FINAL REMARKS

    View Slide

  73. FINAL REMARKS
    • GraphQL is just a spec

    View Slide

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

    View Slide

  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)

    View Slide

  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

    View Slide

  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

    View Slide

  78. https://speakerdeck.com/ubiratansoares

    View Slide

  79. UBIRATAN
    SOARES
    Computer Scientist by ICMC/USP
    Software Engineer, curious guy
    Google Developer Expert for Android
    Teacher, speaker, etc, etc

    View Slide

  80. THANK YOU
    @ubiratanfsoares
    ubiratansoares.github.io
    https://br.linkedin.com/in/ubiratanfsoares

    View Slide